booking-agent-cli 0.1.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.
- booking_agent/__init__.py +6 -0
- booking_agent/authorization.py +450 -0
- booking_agent/backend/__init__.py +217 -0
- booking_agent/backend/live.py +494 -0
- booking_agent/calendar/__init__.py +55 -0
- booking_agent/calendar/filter.py +41 -0
- booking_agent/calendar/google.py +582 -0
- booking_agent/calendar/oauth_listener.py +287 -0
- booking_agent/calendar/scope.py +97 -0
- booking_agent/circuit_breaker.py +116 -0
- booking_agent/config.py +51 -0
- booking_agent/defaults.env +50 -0
- booking_agent/discovery.py +188 -0
- booking_agent/headless.py +463 -0
- booking_agent/http_deadlines.py +43 -0
- booking_agent/http_retry.py +178 -0
- booking_agent/http_trace.py +428 -0
- booking_agent/merchant_pacing.py +73 -0
- booking_agent/models/__init__.py +14 -0
- booking_agent/models/platform.py +200 -0
- booking_agent/models/wire.py +868 -0
- booking_agent/namespace.py +53 -0
- booking_agent/observability.py +143 -0
- booking_agent/platform_profile.py +120 -0
- booking_agent/pop.py +347 -0
- booking_agent/profile_cache.py +130 -0
- booking_agent/registry_url.py +35 -0
- booking_agent/rest_client.py +1493 -0
- booking_agent/secure_file.py +52 -0
- booking_agent/settings.py +110 -0
- booking_agent/signals.py +130 -0
- booking_agent/step_timing.py +168 -0
- booking_agent/ucp_capabilities.py +148 -0
- booking_agent/ucp_checkout.py +1363 -0
- booking_agent/ucp_negotiation.py +184 -0
- booking_agent/ucp_profile.py +410 -0
- booking_agent/usp_methods.py +110 -0
- booking_agent_cli/__init__.py +3 -0
- booking_agent_cli/activity_log.py +106 -0
- booking_agent_cli/booking_poll.py +141 -0
- booking_agent_cli/booking_summary.py +151 -0
- booking_agent_cli/calendar_connection.py +196 -0
- booking_agent_cli/calendar_event.py +611 -0
- booking_agent_cli/calendar_preference.py +176 -0
- booking_agent_cli/catalog.py +864 -0
- booking_agent_cli/checkout_prereq.py +67 -0
- booking_agent_cli/commands/__init__.py +0 -0
- booking_agent_cli/commands/config.py +106 -0
- booking_agent_cli/commands/flow.py +6988 -0
- booking_agent_cli/commands/lowlevel.py +163 -0
- booking_agent_cli/commands/runtime.py +46 -0
- booking_agent_cli/config_loader.py +108 -0
- booking_agent_cli/engine.py +168 -0
- booking_agent_cli/flow_timings.py +34 -0
- booking_agent_cli/geo_eligibility.py +183 -0
- booking_agent_cli/geocode.py +233 -0
- booking_agent_cli/identity.py +104 -0
- booking_agent_cli/link_cli.py +620 -0
- booking_agent_cli/main.py +75 -0
- booking_agent_cli/output.py +199 -0
- booking_agent_cli/payment_helpers.py +884 -0
- booking_agent_cli/payment_token.py +23 -0
- booking_agent_cli/reschedule.py +137 -0
- booking_agent_cli/runtime.py +55 -0
- booking_agent_cli/runtime_prepare.py +129 -0
- booking_agent_cli/search_area.py +111 -0
- booking_agent_cli/session.py +837 -0
- booking_agent_cli/support_bundle_schema.py +557 -0
- booking_agent_cli/support_report.py +1210 -0
- booking_agent_cli/timezone_context.py +314 -0
- booking_agent_cli-0.1.0.dist-info/METADATA +75 -0
- booking_agent_cli-0.1.0.dist-info/RECORD +74 -0
- booking_agent_cli-0.1.0.dist-info/WHEEL +4 -0
- booking_agent_cli-0.1.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"""Platform-side USP orchestration models for booking-agent-cli.
|
|
2
|
+
|
|
3
|
+
These models live on the platform (Booking Agent CLI) side and are NOT part of the
|
|
4
|
+
USP wire protocol. Business-side implementations do not need them.
|
|
5
|
+
"""
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from typing import Any, List, Optional, Union
|
|
8
|
+
|
|
9
|
+
from pydantic import (
|
|
10
|
+
AliasChoices,
|
|
11
|
+
BaseModel,
|
|
12
|
+
ConfigDict,
|
|
13
|
+
Field,
|
|
14
|
+
ValidationError,
|
|
15
|
+
field_validator,
|
|
16
|
+
)
|
|
17
|
+
from pydantic.alias_generators import to_camel
|
|
18
|
+
|
|
19
|
+
from .wire import AvailabilityHint, Coordinates, RegistryBusinessInfo
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class BookingPaymentMode(str, Enum):
|
|
23
|
+
GENERIC = "generic"
|
|
24
|
+
UCP = "ucp"
|
|
25
|
+
REDIRECT = "redirect"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ServiceSearchLocation(BaseModel):
|
|
29
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
|
30
|
+
|
|
31
|
+
coordinates: Coordinates
|
|
32
|
+
radius_km: Optional[float] = None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class RangeMatchMode(str, Enum):
|
|
36
|
+
"""How a service interval S is compared to a registry filter interval F.
|
|
37
|
+
|
|
38
|
+
Mirrors ``schemas/registry.json#/$defs/RangeMatchMode`` (USP §6.3.1).
|
|
39
|
+
Omitted ``match`` on the wire MUST be treated as ``overlap`` by registries.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
OVERLAP = "overlap"
|
|
43
|
+
CONTAINED = "contained"
|
|
44
|
+
CONTAINS = "contains"
|
|
45
|
+
EQUALS = "equals"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class PriceRange(BaseModel):
|
|
49
|
+
"""Registry ``price_range`` filter (``schemas/registry.json#/$defs/PriceRangeFilter``)."""
|
|
50
|
+
|
|
51
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
|
52
|
+
|
|
53
|
+
min: Optional[int] = None
|
|
54
|
+
max: Optional[int] = None
|
|
55
|
+
currency: str = "USD"
|
|
56
|
+
match: Optional[RangeMatchMode] = None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class DurationRange(BaseModel):
|
|
60
|
+
"""Registry ``duration_range`` filter (``schemas/registry.json#/$defs/DurationRangeFilter``)."""
|
|
61
|
+
|
|
62
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
|
63
|
+
|
|
64
|
+
min_minutes: Optional[int] = None
|
|
65
|
+
max_minutes: Optional[int] = None
|
|
66
|
+
match: Optional[RangeMatchMode] = None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class DesiredServiceTimeMoment(BaseModel):
|
|
70
|
+
model_config = ConfigDict(
|
|
71
|
+
alias_generator=to_camel, populate_by_name=True, extra="forbid"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
at: str
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class DesiredServiceTimeRange(BaseModel):
|
|
78
|
+
model_config = ConfigDict(
|
|
79
|
+
alias_generator=to_camel, populate_by_name=True, extra="forbid"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
start: str
|
|
83
|
+
end: str
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class DesiredServiceTimeFrom(BaseModel):
|
|
87
|
+
model_config = ConfigDict(
|
|
88
|
+
alias_generator=to_camel, populate_by_name=True, extra="forbid"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
start: str
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
DesiredServiceTimePreference = Union[
|
|
95
|
+
DesiredServiceTimeMoment,
|
|
96
|
+
DesiredServiceTimeRange,
|
|
97
|
+
DesiredServiceTimeFrom,
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class ServiceSearchIntent(BaseModel):
|
|
102
|
+
"""Platform-side intent object for service discovery (analogous to IntentMandate)."""
|
|
103
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
|
104
|
+
|
|
105
|
+
natural_language_description: str
|
|
106
|
+
location: Optional[ServiceSearchLocation] = None
|
|
107
|
+
verticals: List[str] = []
|
|
108
|
+
categories: List[str] = []
|
|
109
|
+
query: str
|
|
110
|
+
price_range: Optional[PriceRange] = None
|
|
111
|
+
duration_range: Optional[DurationRange] = None
|
|
112
|
+
date_preference: Optional[str] = None
|
|
113
|
+
desired_service_time_ranges: Optional[List[DesiredServiceTimePreference]] = None
|
|
114
|
+
prefer_sooner_availability_slots: Optional[bool] = None
|
|
115
|
+
intent_expiry: str
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# ---------------------------------------------------------------------------
|
|
119
|
+
# Registry search response models (mirrors /registry/search_services response)
|
|
120
|
+
# ---------------------------------------------------------------------------
|
|
121
|
+
|
|
122
|
+
class ServiceSearchResultPrice(BaseModel):
|
|
123
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
|
124
|
+
|
|
125
|
+
model: Optional[str] = None
|
|
126
|
+
amount: Optional[int] = None
|
|
127
|
+
currency: Optional[str] = None
|
|
128
|
+
|
|
129
|
+
@field_validator("amount", mode="before")
|
|
130
|
+
@classmethod
|
|
131
|
+
def _coerce_amount(cls, value: object) -> Optional[int]:
|
|
132
|
+
if value is None or value == "":
|
|
133
|
+
return None
|
|
134
|
+
return int(value)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class ServiceSearchResultLocation(BaseModel):
|
|
138
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
|
139
|
+
|
|
140
|
+
address: Optional[str] = None
|
|
141
|
+
coordinates: Optional[Coordinates] = None
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class RankSignals(BaseModel):
|
|
145
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
|
146
|
+
|
|
147
|
+
relevance: float = Field(ge=0, le=1)
|
|
148
|
+
coverage: Optional[float] = Field(ge=0, le=1)
|
|
149
|
+
density: Optional[float] = Field(ge=0, le=1)
|
|
150
|
+
soonness: Optional[float] = Field(ge=0, le=1)
|
|
151
|
+
hint_usable: bool
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class ServiceSearchResult(BaseModel):
|
|
155
|
+
"""schemas/registry.json#/$defs/ServiceSearchResult.
|
|
156
|
+
|
|
157
|
+
Spec REQUIRES (service_id, service_name, business, category, pricing, timezone).
|
|
158
|
+
``pricing`` (named ``price`` here, the field name the client reads) and
|
|
159
|
+
``timezone`` are Optional: the client accepts results without them.
|
|
160
|
+
"""
|
|
161
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
|
162
|
+
|
|
163
|
+
service_id: str
|
|
164
|
+
service_name: str
|
|
165
|
+
business: RegistryBusinessInfo
|
|
166
|
+
category: str
|
|
167
|
+
duration_minutes: Optional[int] = None
|
|
168
|
+
price: Optional[ServiceSearchResultPrice] = Field(
|
|
169
|
+
default=None,
|
|
170
|
+
validation_alias=AliasChoices("price", "pricing"),
|
|
171
|
+
serialization_alias="pricing",
|
|
172
|
+
)
|
|
173
|
+
location: Optional[ServiceSearchResultLocation] = None
|
|
174
|
+
timezone: Optional[str] = None
|
|
175
|
+
category_ids: Optional[List[str]] = None
|
|
176
|
+
availability_hint: Optional[AvailabilityHint] = None
|
|
177
|
+
rank_signals: Optional[RankSignals] = None
|
|
178
|
+
|
|
179
|
+
@field_validator("availability_hint", mode="before")
|
|
180
|
+
@classmethod
|
|
181
|
+
def _drop_malformed_availability_hint(
|
|
182
|
+
cls, value: Any
|
|
183
|
+
) -> Optional[AvailabilityHint]:
|
|
184
|
+
if value is None or isinstance(value, AvailabilityHint):
|
|
185
|
+
return value
|
|
186
|
+
try:
|
|
187
|
+
return AvailabilityHint.model_validate(value)
|
|
188
|
+
except (ValidationError, TypeError, ValueError):
|
|
189
|
+
return None
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class ServiceSearchPagination(BaseModel):
|
|
193
|
+
"""Pagination metadata; supports cursor- and offset-based styles."""
|
|
194
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
|
195
|
+
|
|
196
|
+
cursor: Optional[str] = None
|
|
197
|
+
has_more: Optional[bool] = None
|
|
198
|
+
count: Optional[int] = None
|
|
199
|
+
offset: Optional[int] = None
|
|
200
|
+
has_next: Optional[bool] = None
|