unitysvc-core 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.
- unitysvc_core/__init__.py +32 -0
- unitysvc_core/models/__init__.py +171 -0
- unitysvc_core/models/base.py +317 -0
- unitysvc_core/models/documents.py +46 -0
- unitysvc_core/models/listing_data.py +115 -0
- unitysvc_core/models/listing_v1.py +55 -0
- unitysvc_core/models/offering_data.py +116 -0
- unitysvc_core/models/offering_v1.py +68 -0
- unitysvc_core/models/pricing.py +1394 -0
- unitysvc_core/models/promotion_data.py +290 -0
- unitysvc_core/models/promotion_v1.py +29 -0
- unitysvc_core/models/provider_data.py +79 -0
- unitysvc_core/models/provider_v1.py +70 -0
- unitysvc_core/models/service.py +135 -0
- unitysvc_core/models/service_group_data.py +178 -0
- unitysvc_core/models/service_group_v1.py +36 -0
- unitysvc_core/models/validators.py +206 -0
- unitysvc_core/py.typed +0 -0
- unitysvc_core/schema/base.json +796 -0
- unitysvc_core/schema/listing_v1.json +2108 -0
- unitysvc_core/schema/offering_v1.json +2133 -0
- unitysvc_core/schema/promotion_v1.json +122 -0
- unitysvc_core/schema/provider_v1.json +379 -0
- unitysvc_core/schema/service_group_v1.json +94 -0
- unitysvc_core/utils.py +434 -0
- unitysvc_core/validator.py +615 -0
- unitysvc_core-0.1.0.dist-info/METADATA +134 -0
- unitysvc_core-0.1.0.dist-info/RECORD +31 -0
- unitysvc_core-0.1.0.dist-info/WHEEL +5 -0
- unitysvc_core-0.1.0.dist-info/licenses/LICENSE +21 -0
- unitysvc_core-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""UnitySVC Core — shared data models and validation helpers.
|
|
2
|
+
|
|
3
|
+
This package is audience-neutral. It contains the pydantic models, JSON
|
|
4
|
+
schemas, and validator consumed by the UnitySVC backend, the customer SDK,
|
|
5
|
+
the admin CLI, and the seller SDK.
|
|
6
|
+
|
|
7
|
+
It intentionally does NOT include any CLI, HTTP client, or audience-
|
|
8
|
+
specific helpers (seller catalog builders, customer query helpers, etc.).
|
|
9
|
+
Those live in the corresponding audience packages (``unitysvc-sellers``,
|
|
10
|
+
``unitysvc`` customer SDK, ``unitysvc-admin``).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
__author__ = """Bo Peng"""
|
|
14
|
+
__email__ = "bo.peng@unitysvc.com"
|
|
15
|
+
|
|
16
|
+
# Shared file / data utilities used by the backend and SDK consumers
|
|
17
|
+
from .utils import (
|
|
18
|
+
compute_file_hash,
|
|
19
|
+
generate_content_based_key,
|
|
20
|
+
get_basename,
|
|
21
|
+
get_file_extension,
|
|
22
|
+
mime_type_to_extension,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
# File utilities
|
|
27
|
+
"compute_file_hash",
|
|
28
|
+
"generate_content_based_key",
|
|
29
|
+
"get_basename",
|
|
30
|
+
"get_file_extension",
|
|
31
|
+
"mime_type_to_extension",
|
|
32
|
+
]
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
from .base import (
|
|
2
|
+
AccessMethodEnum,
|
|
3
|
+
AuthMethodEnum,
|
|
4
|
+
ContentFilterEnum,
|
|
5
|
+
CurrencyEnum,
|
|
6
|
+
DocumentCategoryEnum,
|
|
7
|
+
DocumentContextEnum,
|
|
8
|
+
ListingStatusEnum,
|
|
9
|
+
MimeTypeEnum,
|
|
10
|
+
OfferingStatusEnum,
|
|
11
|
+
OveragePolicyEnum,
|
|
12
|
+
PriceRuleApplyAtEnum,
|
|
13
|
+
PriceRuleStatusEnum,
|
|
14
|
+
PricingTypeEnum,
|
|
15
|
+
ProviderStatusEnum,
|
|
16
|
+
QuotaResetCycleEnum,
|
|
17
|
+
RateLimitUnitEnum,
|
|
18
|
+
RequestTransformEnum,
|
|
19
|
+
SellerTypeEnum,
|
|
20
|
+
ServiceGroupStatusEnum,
|
|
21
|
+
ServiceTypeEnum,
|
|
22
|
+
TimeWindowEnum,
|
|
23
|
+
UpstreamStatusEnum, # Backwards compatibility alias for OfferingStatusEnum
|
|
24
|
+
)
|
|
25
|
+
from .documents import DocumentData
|
|
26
|
+
from .listing_data import ServiceListingData
|
|
27
|
+
from .listing_v1 import ListingV1
|
|
28
|
+
from .offering_data import ServiceOfferingData
|
|
29
|
+
from .offering_v1 import OfferingV1
|
|
30
|
+
from .pricing import (
|
|
31
|
+
AddPriceData,
|
|
32
|
+
BasePriceData,
|
|
33
|
+
ConstantPriceData,
|
|
34
|
+
CountPriceData,
|
|
35
|
+
DataPriceData,
|
|
36
|
+
ExprPriceData,
|
|
37
|
+
FirstPriceData,
|
|
38
|
+
GraduatedPriceData,
|
|
39
|
+
GraduatedTier,
|
|
40
|
+
ImagePriceData,
|
|
41
|
+
MaxPriceData,
|
|
42
|
+
MinPriceData,
|
|
43
|
+
MultiplyPriceData,
|
|
44
|
+
PercentageStr,
|
|
45
|
+
PriceStr,
|
|
46
|
+
PriceTier,
|
|
47
|
+
Pricing,
|
|
48
|
+
RevenueSharePriceData,
|
|
49
|
+
StepPriceData,
|
|
50
|
+
TieredPriceData,
|
|
51
|
+
TimePriceData,
|
|
52
|
+
TokenPriceData,
|
|
53
|
+
UsageData,
|
|
54
|
+
validate_pricing,
|
|
55
|
+
)
|
|
56
|
+
from .promotion_data import (
|
|
57
|
+
PROMOTION_SCHEMA_VERSION,
|
|
58
|
+
PromotionData,
|
|
59
|
+
describe_scope,
|
|
60
|
+
is_promotion_file,
|
|
61
|
+
strip_schema_field,
|
|
62
|
+
validate_promotion,
|
|
63
|
+
)
|
|
64
|
+
from .promotion_v1 import PromotionV1
|
|
65
|
+
from .provider_data import ProviderData
|
|
66
|
+
from .provider_v1 import ProviderV1
|
|
67
|
+
from .service import (
|
|
68
|
+
AccessInterfaceData,
|
|
69
|
+
RateLimit,
|
|
70
|
+
ServiceConstraints,
|
|
71
|
+
UpstreamAccessConfigData,
|
|
72
|
+
)
|
|
73
|
+
from .service_group_data import (
|
|
74
|
+
SERVICE_GROUP_SCHEMA_VERSION,
|
|
75
|
+
ServiceGroupData,
|
|
76
|
+
is_service_group_file,
|
|
77
|
+
validate_service_group,
|
|
78
|
+
)
|
|
79
|
+
from .service_group_v1 import ServiceGroupV1
|
|
80
|
+
from .validators import (
|
|
81
|
+
SUPPORTED_SERVICE_OPTIONS,
|
|
82
|
+
suggest_valid_name,
|
|
83
|
+
validate_name,
|
|
84
|
+
validate_service_options,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
__all__ = [
|
|
88
|
+
# V1 models (for file validation)
|
|
89
|
+
"ProviderV1",
|
|
90
|
+
"OfferingV1",
|
|
91
|
+
"ListingV1",
|
|
92
|
+
"PromotionV1",
|
|
93
|
+
"ServiceGroupV1",
|
|
94
|
+
# Data models (for API/backend use)
|
|
95
|
+
"ProviderData",
|
|
96
|
+
"ServiceOfferingData",
|
|
97
|
+
"ServiceListingData",
|
|
98
|
+
"PromotionData",
|
|
99
|
+
"ServiceGroupData",
|
|
100
|
+
# Shared / access models
|
|
101
|
+
"DocumentData",
|
|
102
|
+
"AccessInterfaceData",
|
|
103
|
+
"UpstreamAccessConfigData",
|
|
104
|
+
"RateLimit",
|
|
105
|
+
"ServiceConstraints",
|
|
106
|
+
# Enums
|
|
107
|
+
"AccessMethodEnum",
|
|
108
|
+
"AuthMethodEnum",
|
|
109
|
+
"ContentFilterEnum",
|
|
110
|
+
"CurrencyEnum",
|
|
111
|
+
"DocumentCategoryEnum",
|
|
112
|
+
"DocumentContextEnum",
|
|
113
|
+
"ListingStatusEnum",
|
|
114
|
+
"MimeTypeEnum",
|
|
115
|
+
"OfferingStatusEnum",
|
|
116
|
+
"OveragePolicyEnum",
|
|
117
|
+
"PriceRuleApplyAtEnum",
|
|
118
|
+
"PriceRuleStatusEnum",
|
|
119
|
+
"PricingTypeEnum",
|
|
120
|
+
"ProviderStatusEnum",
|
|
121
|
+
"QuotaResetCycleEnum",
|
|
122
|
+
"RateLimitUnitEnum",
|
|
123
|
+
"RequestTransformEnum",
|
|
124
|
+
"SellerTypeEnum",
|
|
125
|
+
"ServiceGroupStatusEnum",
|
|
126
|
+
"ServiceTypeEnum",
|
|
127
|
+
"TimeWindowEnum",
|
|
128
|
+
"UpstreamStatusEnum", # Backwards compatibility alias for OfferingStatusEnum
|
|
129
|
+
# Pricing — primitives
|
|
130
|
+
"PriceStr",
|
|
131
|
+
"PercentageStr",
|
|
132
|
+
"UsageData",
|
|
133
|
+
"Pricing",
|
|
134
|
+
"validate_pricing",
|
|
135
|
+
"BasePriceData",
|
|
136
|
+
# Pricing — simple types
|
|
137
|
+
"TokenPriceData",
|
|
138
|
+
"TimePriceData",
|
|
139
|
+
"DataPriceData",
|
|
140
|
+
"CountPriceData",
|
|
141
|
+
"ImagePriceData",
|
|
142
|
+
"StepPriceData",
|
|
143
|
+
"RevenueSharePriceData",
|
|
144
|
+
"ConstantPriceData",
|
|
145
|
+
# Pricing — composite types
|
|
146
|
+
"AddPriceData",
|
|
147
|
+
"MultiplyPriceData",
|
|
148
|
+
"MaxPriceData",
|
|
149
|
+
"MinPriceData",
|
|
150
|
+
"FirstPriceData",
|
|
151
|
+
"TieredPriceData",
|
|
152
|
+
"GraduatedPriceData",
|
|
153
|
+
"ExprPriceData",
|
|
154
|
+
"PriceTier",
|
|
155
|
+
"GraduatedTier",
|
|
156
|
+
# Validators
|
|
157
|
+
"SUPPORTED_SERVICE_OPTIONS",
|
|
158
|
+
"validate_name",
|
|
159
|
+
"validate_service_options",
|
|
160
|
+
"suggest_valid_name",
|
|
161
|
+
# Promotions
|
|
162
|
+
"PROMOTION_SCHEMA_VERSION",
|
|
163
|
+
"is_promotion_file",
|
|
164
|
+
"describe_scope",
|
|
165
|
+
"strip_schema_field",
|
|
166
|
+
"validate_promotion",
|
|
167
|
+
# Service Groups
|
|
168
|
+
"SERVICE_GROUP_SCHEMA_VERSION",
|
|
169
|
+
"is_service_group_file",
|
|
170
|
+
"validate_service_group",
|
|
171
|
+
]
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"""Enum types and basic definitions shared across the data models.
|
|
2
|
+
|
|
3
|
+
This module contains only enums and simple constants. Data classes with
|
|
4
|
+
behavior (pricing, documents, service constraints, etc.) and validation
|
|
5
|
+
functions live in their own modules:
|
|
6
|
+
|
|
7
|
+
- ``pricing.py`` — pricing types and cost calculation
|
|
8
|
+
- ``documents.py`` — DocumentData
|
|
9
|
+
- ``service.py`` — RateLimit, ServiceConstraints, AccessInterfaceData, UpstreamAccessConfigData
|
|
10
|
+
- ``validators.py`` — validate_name, validate_service_options, suggest_valid_name
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from enum import StrEnum
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AccessMethodEnum(StrEnum):
|
|
19
|
+
http = "http"
|
|
20
|
+
websocket = "websocket"
|
|
21
|
+
grpc = "grpc"
|
|
22
|
+
smtp = "smtp"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class CurrencyEnum(StrEnum):
|
|
26
|
+
"""Supported currency codes for pricing."""
|
|
27
|
+
|
|
28
|
+
# Traditional currencies
|
|
29
|
+
USD = "USD" # US Dollar
|
|
30
|
+
EUR = "EUR" # Euro
|
|
31
|
+
GBP = "GBP" # British Pound
|
|
32
|
+
JPY = "JPY" # Japanese Yen
|
|
33
|
+
CNY = "CNY" # Chinese Yuan
|
|
34
|
+
CAD = "CAD" # Canadian Dollar
|
|
35
|
+
AUD = "AUD" # Australian Dollar
|
|
36
|
+
CHF = "CHF" # Swiss Franc
|
|
37
|
+
INR = "INR" # Indian Rupee
|
|
38
|
+
KRW = "KRW" # Korean Won
|
|
39
|
+
|
|
40
|
+
# Cryptocurrencies
|
|
41
|
+
BTC = "BTC" # Bitcoin
|
|
42
|
+
ETH = "ETH" # Ethereum
|
|
43
|
+
USDT = "USDT" # Tether
|
|
44
|
+
USDC = "USDC" # USD Coin
|
|
45
|
+
TAO = "TAO" # Bittensor TAO
|
|
46
|
+
|
|
47
|
+
# Credits/Points (for platforms that use credits)
|
|
48
|
+
CREDITS = "CREDITS" # Generic credits system
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class AuthMethodEnum(StrEnum):
|
|
52
|
+
api_key = "api_key"
|
|
53
|
+
oauth = "oauth"
|
|
54
|
+
jwt = "jwt"
|
|
55
|
+
bearer_token = "bearer_token"
|
|
56
|
+
basic_auth = "basic_auth"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ContentFilterEnum(StrEnum):
|
|
60
|
+
adult = "adult"
|
|
61
|
+
violence = "violence"
|
|
62
|
+
hate_speech = "hate_speech"
|
|
63
|
+
profanity = "profanity"
|
|
64
|
+
pii = "pii" # Personally Identifiable Information
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class DocumentContextEnum(StrEnum):
|
|
68
|
+
service_definition = "service_definition" # Documents belong to ServiceDefinition
|
|
69
|
+
service_offering = "service_offering" # Documents belong to ServiceOffering
|
|
70
|
+
service_listing = "service_listing" # Documents belong to ServiceListing
|
|
71
|
+
user = "user" # can be for seller, subscriber, consumer
|
|
72
|
+
# Backend-specific contexts
|
|
73
|
+
seller = "seller" # Documents belong to Seller
|
|
74
|
+
provider = "provider" # Documents belong to Provider
|
|
75
|
+
blog_post = "blog_post" # Documents belong to BlogPost
|
|
76
|
+
#
|
|
77
|
+
customer_statement = "customer_statement"
|
|
78
|
+
seller_invoice = "seller_invoice"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class DocumentCategoryEnum(StrEnum):
|
|
82
|
+
getting_started = "getting_started"
|
|
83
|
+
api_reference = "api_reference"
|
|
84
|
+
tutorial = "tutorial"
|
|
85
|
+
code_example = "code_example"
|
|
86
|
+
code_example_output = "code_example_output"
|
|
87
|
+
connectivity_test = "connectivity_test" # Test connectivity & performance (not visible to users)
|
|
88
|
+
request_template = "request_template" # Default request body for playground pre-fill
|
|
89
|
+
use_case = "use_case"
|
|
90
|
+
troubleshooting = "troubleshooting"
|
|
91
|
+
changelog = "changelog"
|
|
92
|
+
best_practice = "best_practice"
|
|
93
|
+
specification = "specification"
|
|
94
|
+
service_level_agreement = "service_level_agreement"
|
|
95
|
+
terms_of_service = "terms_of_service"
|
|
96
|
+
statement = "statement"
|
|
97
|
+
invoice = "invoice"
|
|
98
|
+
logo = "logo"
|
|
99
|
+
avatar = "avatar"
|
|
100
|
+
blog_content = "blog_content" # Main content for blog posts
|
|
101
|
+
blog_banner = "blog_banner" # Banner/cover image for blog posts
|
|
102
|
+
attachment = "attachment" # Attachments for markdown documents
|
|
103
|
+
other = "other"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class MimeTypeEnum(StrEnum):
|
|
107
|
+
markdown = "markdown"
|
|
108
|
+
python = "python"
|
|
109
|
+
javascript = "javascript"
|
|
110
|
+
bash = "bash"
|
|
111
|
+
html = "html"
|
|
112
|
+
json = "json"
|
|
113
|
+
text = "text"
|
|
114
|
+
pdf = "pdf"
|
|
115
|
+
jpeg = "jpeg"
|
|
116
|
+
png = "png"
|
|
117
|
+
svg = "svg"
|
|
118
|
+
url = "url"
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class ServiceGroupStatusEnum(StrEnum):
|
|
122
|
+
draft = "draft"
|
|
123
|
+
active = "active"
|
|
124
|
+
private = "private"
|
|
125
|
+
archived = "archived"
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class SellerTypeEnum(StrEnum):
|
|
129
|
+
individual = "individual"
|
|
130
|
+
organization = "organization"
|
|
131
|
+
partnership = "partnership"
|
|
132
|
+
corporation = "corporation"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class ListingStatusEnum(StrEnum):
|
|
136
|
+
"""
|
|
137
|
+
Status values that sellers can set for listings.
|
|
138
|
+
|
|
139
|
+
Seller-accessible statuses:
|
|
140
|
+
- draft: Work in progress, skipped during publish (won't be sent to backend)
|
|
141
|
+
- ready: Complete and ready for admin review/testing
|
|
142
|
+
- deprecated: Retired/end of life, no longer offered
|
|
143
|
+
|
|
144
|
+
Note: Admin-managed workflow statuses (upstream_ready, downstream_ready, in_service)
|
|
145
|
+
are set by the backend admin after testing and validation. These are not included in this
|
|
146
|
+
enum since sellers cannot set them through the CLI tool.
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
draft = "draft"
|
|
150
|
+
ready = "ready"
|
|
151
|
+
deprecated = "deprecated"
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class OveragePolicyEnum(StrEnum):
|
|
155
|
+
block = "block" # Block requests when quota exceeded
|
|
156
|
+
throttle = "throttle" # Reduce rate when quota exceeded
|
|
157
|
+
charge = "charge" # Allow with additional charges
|
|
158
|
+
queue = "queue" # Queue requests until quota resets
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class PricingTypeEnum(StrEnum):
|
|
162
|
+
"""
|
|
163
|
+
Pricing type determines the structure and calculation method.
|
|
164
|
+
The type is stored as the 'type' field in the pricing object.
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
# Basic pricing types
|
|
168
|
+
one_million_tokens = "one_million_tokens"
|
|
169
|
+
one_thousand_tokens = "one_thousand_tokens"
|
|
170
|
+
one_token = "one_token"
|
|
171
|
+
one_second = "one_second"
|
|
172
|
+
one_minute = "one_minute"
|
|
173
|
+
one_hour = "one_hour"
|
|
174
|
+
one_day = "one_day"
|
|
175
|
+
one_month = "one_month"
|
|
176
|
+
one_byte = "one_byte"
|
|
177
|
+
one_kilobyte = "one_kilobyte"
|
|
178
|
+
one_megabyte = "one_megabyte"
|
|
179
|
+
one_gigabyte = "one_gigabyte"
|
|
180
|
+
one_thousand = "one_thousand"
|
|
181
|
+
one_million = "one_million"
|
|
182
|
+
image = "image"
|
|
183
|
+
step = "step"
|
|
184
|
+
# Seller-only: seller receives a percentage of what customer pays
|
|
185
|
+
revenue_share = "revenue_share"
|
|
186
|
+
# Composite pricing types
|
|
187
|
+
constant = "constant" # Fixed amount (fee or discount)
|
|
188
|
+
add = "add" # Sum of multiple prices
|
|
189
|
+
multiply = "multiply" # Base price multiplied by factor
|
|
190
|
+
max = "max" # Highest of multiple prices (lenient)
|
|
191
|
+
min = "min" # Lowest of multiple prices (lenient)
|
|
192
|
+
first = "first" # First applicable price (lenient)
|
|
193
|
+
# Tiered pricing types
|
|
194
|
+
tiered = "tiered" # Volume-based tiers (all units at one tier's price)
|
|
195
|
+
graduated = "graduated" # Graduated tiers (each tier's units at that rate)
|
|
196
|
+
# Expression-based pricing (payout_price only)
|
|
197
|
+
expr = "expr" # Arbitrary expression using usage metrics
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class QuotaResetCycleEnum(StrEnum):
|
|
202
|
+
daily = "daily"
|
|
203
|
+
weekly = "weekly"
|
|
204
|
+
monthly = "monthly"
|
|
205
|
+
yearly = "yearly"
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class RateLimitUnitEnum(StrEnum):
|
|
209
|
+
requests = "requests"
|
|
210
|
+
tokens = "tokens"
|
|
211
|
+
input_tokens = "input_tokens"
|
|
212
|
+
output_tokens = "output_tokens"
|
|
213
|
+
bytes = "bytes"
|
|
214
|
+
concurrent = "concurrent"
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class RequestTransformEnum(StrEnum):
|
|
218
|
+
# https://docs.api7.ai/hub/proxy-rewrite
|
|
219
|
+
proxy_rewrite = "proxy_rewrite"
|
|
220
|
+
# https://docs.api7.ai/hub/body-transformer
|
|
221
|
+
body_transformer = "body_transformer"
|
|
222
|
+
# Simple body replacement from rendered enrollment data
|
|
223
|
+
set_body = "set_body"
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class ServiceTypeEnum(StrEnum):
|
|
227
|
+
"""Broad service category — defines the access pattern and protocol.
|
|
228
|
+
|
|
229
|
+
AI modalities (vision, tools, rerank, etc.) are tracked via the
|
|
230
|
+
`capabilities` list on ServiceOffering, not service_type.
|
|
231
|
+
"""
|
|
232
|
+
|
|
233
|
+
# === AI / ML services (HTTP API) ===
|
|
234
|
+
llm = "llm" # Language models, chat completions
|
|
235
|
+
embedding = "embedding" # Text/vector embedding
|
|
236
|
+
image_generation = "image_generation" # Image creation/editing
|
|
237
|
+
|
|
238
|
+
# === Communication services ===
|
|
239
|
+
notification = "notification" # Push notifications (HTTP)
|
|
240
|
+
email = "email" # Email delivery (SMTP gateway)
|
|
241
|
+
|
|
242
|
+
# === Content services ===
|
|
243
|
+
content = "content" # Downloadable files, datasets, images, software
|
|
244
|
+
streaming = "streaming" # Video, audio, live feeds (persistent connection)
|
|
245
|
+
|
|
246
|
+
# === Compute services ===
|
|
247
|
+
compute = "compute" # GPU instances, dev environments (SSH/WireGuard)
|
|
248
|
+
|
|
249
|
+
# === Infrastructure services ===
|
|
250
|
+
database = "database" # Managed DB/cache access (SSH tunnel)
|
|
251
|
+
monitoring = "monitoring" # Uptime checks, health monitoring
|
|
252
|
+
analytics = "analytics" # Recommendation, anomaly detection, forecasting
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class TimeWindowEnum(StrEnum):
|
|
256
|
+
second = "second"
|
|
257
|
+
minute = "minute"
|
|
258
|
+
hour = "hour"
|
|
259
|
+
day = "day"
|
|
260
|
+
month = "month"
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
class OfferingStatusEnum(StrEnum):
|
|
264
|
+
"""
|
|
265
|
+
Status values that sellers can set for service offerings.
|
|
266
|
+
|
|
267
|
+
Seller-accessible statuses:
|
|
268
|
+
- draft: Work in progress, skipped during publish
|
|
269
|
+
- ready: Complete and ready for admin review
|
|
270
|
+
- deprecated: Service is retired/end of life
|
|
271
|
+
"""
|
|
272
|
+
|
|
273
|
+
draft = "draft"
|
|
274
|
+
ready = "ready"
|
|
275
|
+
deprecated = "deprecated"
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
# Backwards compatibility alias
|
|
279
|
+
UpstreamStatusEnum = OfferingStatusEnum
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
class ProviderStatusEnum(StrEnum):
|
|
283
|
+
"""
|
|
284
|
+
Status values that sellers can set for providers.
|
|
285
|
+
|
|
286
|
+
Seller-accessible statuses:
|
|
287
|
+
- draft: Work in progress, skipped during publish
|
|
288
|
+
- ready: Complete and ready for admin review
|
|
289
|
+
- deprecated: Provider is retired/end of life
|
|
290
|
+
"""
|
|
291
|
+
|
|
292
|
+
draft = "draft"
|
|
293
|
+
ready = "ready"
|
|
294
|
+
deprecated = "deprecated"
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class PriceRuleApplyAtEnum(StrEnum):
|
|
298
|
+
"""When the price rule is applied."""
|
|
299
|
+
|
|
300
|
+
request = "request" # Applied per API call
|
|
301
|
+
statement = "statement" # Applied during billing/statement generation
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class PriceRuleStatusEnum(StrEnum):
|
|
306
|
+
"""Seller-facing status values for promotions.
|
|
307
|
+
|
|
308
|
+
The backend may define additional statuses (scheduled, expired,
|
|
309
|
+
cancelled) for internal lifecycle management, but sellers only
|
|
310
|
+
interact with these three.
|
|
311
|
+
"""
|
|
312
|
+
|
|
313
|
+
draft = "draft" # Not yet active, can be edited
|
|
314
|
+
active = "active" # Currently active and applied
|
|
315
|
+
paused = "paused" # Temporarily disabled
|
|
316
|
+
|
|
317
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Document data model — used by provider, offering, listing, and promotion files."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
8
|
+
|
|
9
|
+
from .base import DocumentCategoryEnum, MimeTypeEnum
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DocumentData(BaseModel):
|
|
13
|
+
"""Document data for SDK/API payloads.
|
|
14
|
+
|
|
15
|
+
Note: The document title is NOT stored here - it's the key in the documents dict.
|
|
16
|
+
When stored in the database, the backend extracts the key as the title field.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
model_config = ConfigDict(extra="forbid")
|
|
20
|
+
|
|
21
|
+
description: str | None = Field(default=None, max_length=500, description="Document description")
|
|
22
|
+
mime_type: MimeTypeEnum = Field(description="Document MIME type")
|
|
23
|
+
version: str | None = Field(default=None, max_length=50, description="Document version")
|
|
24
|
+
category: DocumentCategoryEnum = Field(description="Document category for organization and filtering")
|
|
25
|
+
meta: dict[str, Any] | None = Field(
|
|
26
|
+
default=None,
|
|
27
|
+
description="JSON containing operation stats",
|
|
28
|
+
)
|
|
29
|
+
file_path: str | None = Field(
|
|
30
|
+
default=None,
|
|
31
|
+
max_length=1000,
|
|
32
|
+
description="Path to file to upload (mutually exclusive with external_url)",
|
|
33
|
+
)
|
|
34
|
+
external_url: str | None = Field(
|
|
35
|
+
default=None,
|
|
36
|
+
max_length=1000,
|
|
37
|
+
description="External URL for the document (mutually exclusive with object_key)",
|
|
38
|
+
)
|
|
39
|
+
sort_order: int = Field(default=0, description="Sort order within category")
|
|
40
|
+
is_active: bool = Field(default=True, description="Whether document is active")
|
|
41
|
+
is_public: bool = Field(
|
|
42
|
+
default=False,
|
|
43
|
+
description="Whether document is publicly accessible without authentication",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Base data models for service listings.
|
|
2
|
+
|
|
3
|
+
This module defines `ServiceListingData`, a base model containing the core fields
|
|
4
|
+
for service listing data that is shared between:
|
|
5
|
+
- unitysvc-core (CLI): Used for file-based listing definitions
|
|
6
|
+
- unitysvc (backend): Used for API payloads and database operations
|
|
7
|
+
|
|
8
|
+
The `ListingV1` model extends this with file-specific fields like `schema_version`
|
|
9
|
+
and `time_created` for data file validation.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import Any
|
|
13
|
+
from uuid import UUID
|
|
14
|
+
|
|
15
|
+
from pydantic import BaseModel, Field
|
|
16
|
+
|
|
17
|
+
from .base import CurrencyEnum, ListingStatusEnum
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ServiceListingData(BaseModel):
|
|
21
|
+
"""
|
|
22
|
+
Base data structure for service listing information.
|
|
23
|
+
|
|
24
|
+
This model contains the core fields needed to describe a service listing,
|
|
25
|
+
without file-specific validation fields. It serves as:
|
|
26
|
+
|
|
27
|
+
1. The base class for `ListingV1` in unitysvc-core (with additional
|
|
28
|
+
schema_version and time_created fields for file validation)
|
|
29
|
+
|
|
30
|
+
2. The data structure imported by unitysvc backend for:
|
|
31
|
+
- API payload validation
|
|
32
|
+
- Database comparison logic in find_and_compare_service_listing()
|
|
33
|
+
- Publish operations from CLI
|
|
34
|
+
|
|
35
|
+
Key characteristics:
|
|
36
|
+
- Contains all user-provided data without system-generated IDs
|
|
37
|
+
- Does not include permission/audit fields (handled by backend CRUD layer)
|
|
38
|
+
- Uses dict types for nested structures to maintain flexibility between
|
|
39
|
+
file definitions and database operations
|
|
40
|
+
- Service/provider relationships are determined by file location (SDK mode) or
|
|
41
|
+
by being published together in a single API call (API mode)
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
model_config = {"extra": "ignore"}
|
|
45
|
+
|
|
46
|
+
# Service ID for updates (set by SDK after first publish)
|
|
47
|
+
# When provided, updates the existing service. When absent, creates a new service.
|
|
48
|
+
service_id: UUID | None = Field(
|
|
49
|
+
default=None,
|
|
50
|
+
description="Service ID from previous publish. If provided, updates existing service. "
|
|
51
|
+
"Stored in override file (e.g., listing.override.json) by SDK after first publish.",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Listing identification
|
|
55
|
+
name: str | None = Field(
|
|
56
|
+
default=None,
|
|
57
|
+
max_length=255,
|
|
58
|
+
description="Name identifier for the service listing (defaults to offering name if not provided)",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Display name for UI (optional - falls back to Service.name derived from offering/listing name)
|
|
62
|
+
display_name: str | None = Field(
|
|
63
|
+
default=None,
|
|
64
|
+
max_length=200,
|
|
65
|
+
description="Human-readable listing name (e.g., 'Premium GPT-4 Access', 'Enterprise AI Services')",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Status - seller-accessible statuses
|
|
69
|
+
status: ListingStatusEnum = Field(
|
|
70
|
+
default=ListingStatusEnum.draft,
|
|
71
|
+
description="Listing status: draft (skip publish), ready (ready for admin review), or deprecated (retired)",
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# List pricing
|
|
75
|
+
list_price: dict[str, Any] | None = Field(
|
|
76
|
+
default=None,
|
|
77
|
+
description="List price: Listed price for customers per unit of service usage",
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Currency for list_price
|
|
81
|
+
currency: CurrencyEnum = Field(
|
|
82
|
+
default=CurrencyEnum.USD,
|
|
83
|
+
description="Currency for list_price (indexed for filtering)",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Access interfaces (keyed by name)
|
|
87
|
+
user_access_interfaces: dict[str, dict[str, Any]] | None = Field(
|
|
88
|
+
default=None,
|
|
89
|
+
description="User access interfaces for the listing, keyed by name",
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Documents (keyed by title)
|
|
93
|
+
documents: dict[str, dict[str, Any]] | None = Field(
|
|
94
|
+
default=None,
|
|
95
|
+
description="Documents associated with the listing, keyed by title (e.g., service level agreements)",
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# User parameters
|
|
99
|
+
user_parameters_schema: dict[str, Any] | None = Field(
|
|
100
|
+
default=None,
|
|
101
|
+
description="JSON Schema for user parameters",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
user_parameters_ui_schema: dict[str, Any] | None = Field(
|
|
105
|
+
default=None,
|
|
106
|
+
description="UI schema for user parameters form rendering",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# Service-specific options
|
|
110
|
+
service_options: dict[str, Any] | None = Field(
|
|
111
|
+
default=None,
|
|
112
|
+
description="Service-specific options that modify backend behavior. "
|
|
113
|
+
"Keys are option names, values are option configurations. "
|
|
114
|
+
"The backend decides which options it supports.",
|
|
115
|
+
)
|