Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
A
aisbf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexlab
aisbf
Commits
b62c119b
Commit
b62c119b
authored
May 12, 2026
by
Stefy Lanza (nextime / spora )
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: resolve market references at runtime
parent
e6fd64d9
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
260 additions
and
3 deletions
+260
-3
market.py
aisbf/routes/dashboard/market.py
+21
-0
user_api.py
aisbf/routes/user_api.py
+41
-0
test_dashboard_user_market_controls.py
tests/routes/test_dashboard_user_market_controls.py
+3
-3
test_market_reference_imports.py
tests/routes/test_market_reference_imports.py
+195
-0
No files found.
aisbf/routes/dashboard/market.py
View file @
b62c119b
...
...
@@ -234,6 +234,27 @@ def _apply_listing_derived_fields(listing: dict, db):
return
_attach_analytics_snapshot
(
listing
)
async
def
resolve_market_reference
(
reference_id
:
int
,
user_id
:
int
)
->
dict
:
db
=
DatabaseRegistry
.
get_config_database
()
reference
=
db
.
get_market_import_reference
(
reference_id
)
if
not
reference
or
reference
.
get
(
'user_id'
)
!=
user_id
:
raise
ValueError
(
'market reference not found'
)
listing
=
db
.
get_market_listing
(
reference
.
get
(
'listing_id'
))
if
not
listing
or
not
listing
.
get
(
'is_active'
):
raise
ValueError
(
'market reference unavailable'
)
return
{
'reference'
:
reference
,
'listing'
:
listing
,
'listing_id'
:
listing
.
get
(
'id'
),
'owner_user_id'
:
listing
.
get
(
'owner_user_id'
),
'owner_username'
:
listing
.
get
(
'owner_username'
),
'source_type'
:
listing
.
get
(
'source_type'
),
'source_id'
:
listing
.
get
(
'source_id'
),
}
def
_listing_scope_priority
(
listing
:
dict
)
->
int
:
return
1
if
listing
.
get
(
'source_scope'
)
==
'global'
else
0
...
...
aisbf/routes/user_api.py
View file @
b62c119b
...
...
@@ -6,6 +6,7 @@ from aisbf.models import ChatCompletionRequest
from
aisbf.database
import
DatabaseRegistry
from
aisbf.app.model_cache
import
get_provider_models
from
aisbf.studio_services
import
studio_service
from
aisbf.routes.dashboard.market
import
resolve_market_reference
router
=
APIRouter
()
_config
=
None
...
...
@@ -50,6 +51,27 @@ def parse_provider_from_model(model: str) -> tuple[str, str]:
return
None
,
model
async
def
_resolve_runtime_market_reference
(
handler
,
resource_id
:
str
,
user_id
:
int
,
expected_type
:
str
)
->
dict
|
None
:
if
not
user_id
or
not
resource_id
.
startswith
(
'market-ref:'
):
return
None
if
resource_id
not
in
getattr
(
handler
,
'user_providers'
,
{})
and
resource_id
not
in
getattr
(
handler
,
'rotations'
,
{})
and
resource_id
not
in
getattr
(
handler
,
'autoselects'
,
{}):
return
None
try
:
reference_id
=
int
(
resource_id
.
split
(
':'
,
1
)[
1
])
except
(
TypeError
,
ValueError
):
raise
HTTPException
(
status_code
=
400
,
detail
=
'Invalid market reference id'
)
try
:
resolved
=
await
resolve_market_reference
(
reference_id
,
user_id
)
except
ValueError
as
exc
:
message
=
str
(
exc
)
if
'unavailable'
in
message
:
raise
HTTPException
(
status_code
=
400
,
detail
=
'Market reference unavailable'
)
raise
HTTPException
(
status_code
=
404
,
detail
=
'Market reference not found'
)
if
resolved
.
get
(
'source_type'
)
!=
expected_type
:
raise
HTTPException
(
status_code
=
400
,
detail
=
'Market reference type mismatch'
)
return
resolved
def
_normalize_studio_proxy_body
(
endpoint_path
:
str
,
body
:
dict
)
->
dict
:
normalized
=
dict
(
body
or
{})
...
...
@@ -349,6 +371,12 @@ async def user_chat_completions(request: Request, username: str, body: ChatCompl
body_dict
=
body
.
model_dump
()
if
provider_id
==
"user-autoselect"
:
handler
=
_get_user_handler
(
'autoselect'
,
user_id
)
market_reference
=
await
_resolve_runtime_market_reference
(
handler
,
actual_model
,
user_id
,
'autoselect'
)
if
market_reference
:
owner_handler
=
_get_user_handler
(
'autoselect'
,
market_reference
[
'owner_user_id'
])
body_dict
[
'model'
]
=
market_reference
[
'source_id'
]
token_id
=
getattr
(
request
.
state
,
'token_id'
,
None
)
return
await
owner_handler
.
handle_autoselect_request
(
market_reference
[
'source_id'
],
body_dict
,
user_id
,
token_id
)
if
actual_model
not
in
handler
.
user_autoselects
:
raise
HTTPException
(
status_code
=
400
,
detail
=
f
"User autoselect '{actual_model}' not found. Available: {list(handler.user_autoselects.keys())}"
)
body_dict
[
'model'
]
=
actual_model
...
...
@@ -359,6 +387,12 @@ async def user_chat_completions(request: Request, username: str, body: ChatCompl
return
await
handler
.
handle_autoselect_request
(
actual_model
,
body_dict
,
user_id
,
token_id
)
if
provider_id
==
"user-rotation"
:
handler
=
_get_user_handler
(
'rotation'
,
user_id
)
market_reference
=
await
_resolve_runtime_market_reference
(
handler
,
actual_model
,
user_id
,
'rotation'
)
if
market_reference
:
owner_handler
=
_get_user_handler
(
'rotation'
,
market_reference
[
'owner_user_id'
])
body_dict
[
'model'
]
=
market_reference
[
'source_id'
]
token_id
=
getattr
(
request
.
state
,
'token_id'
,
None
)
return
await
owner_handler
.
handle_rotation_request
(
market_reference
[
'source_id'
],
body_dict
,
user_id
,
token_id
)
if
actual_model
not
in
handler
.
rotations
:
raise
HTTPException
(
status_code
=
400
,
detail
=
f
"User rotation '{actual_model}' not found. Available: {list(handler.rotations.keys())}"
)
body_dict
[
'model'
]
=
actual_model
...
...
@@ -366,6 +400,13 @@ async def user_chat_completions(request: Request, username: str, body: ChatCompl
return
await
handler
.
handle_rotation_request
(
actual_model
,
body_dict
,
user_id
,
token_id
)
if
provider_id
==
"user-provider"
:
handler
=
_get_user_handler
(
'request'
,
user_id
)
market_reference
=
await
_resolve_runtime_market_reference
(
handler
,
actual_model
,
user_id
,
'provider'
)
if
market_reference
:
owner_handler
=
_get_user_handler
(
'request'
,
market_reference
[
'owner_user_id'
])
body_dict
[
'model'
]
=
market_reference
[
'source_id'
]
if
body
.
stream
:
return
await
owner_handler
.
handle_streaming_chat_completion
(
request
,
market_reference
[
'source_id'
],
body_dict
)
return
await
owner_handler
.
handle_chat_completion
(
request
,
market_reference
[
'source_id'
],
body_dict
)
if
actual_model
not
in
handler
.
user_providers
:
raise
HTTPException
(
status_code
=
400
,
detail
=
f
"User provider '{actual_model}' not found. Available: {list(handler.user_providers.keys())}"
)
body_dict
[
'model'
]
=
actual_model
...
...
tests/routes/test_dashboard_user_market_controls.py
View file @
b62c119b
...
...
@@ -234,7 +234,7 @@ def test_ensure_market_enabled_respects_market_settings_enabled_contract(monkeyp
assert
settings
[
"enabled"
]
is
False
def
test_admin_payment_settings_
embeds_market_admin_controls_and_listings
(
monkeypatch
):
def
test_admin_payment_settings_
links_to_dedicated_market_admin_page
(
monkeypatch
):
db
=
MarketSettingsDbStub
()
templates
=
TemplateCapture
()
client
=
TestClient
(
app
)
...
...
@@ -248,10 +248,10 @@ def test_admin_payment_settings_embeds_market_admin_controls_and_listings(monkey
assert
response
.
status_code
==
200
assert
templates
.
calls
[
-
1
][
"name"
]
==
"dashboard/admin_payment_settings.html"
assert
templates
.
calls
[
-
1
][
"context"
][
"market_settings"
][
"enabled"
]
is
True
assert
templates
.
calls
[
-
1
][
"context"
][
"market_listings"
][
0
][
"title"
]
==
"Flux Dev Pack"
assert
"market_listings"
not
in
templates
.
calls
[
-
1
][
"context"
]
assert
"Enable market"
in
response
.
text
assert
"Market Administration"
in
response
.
text
assert
"
Flux Dev Pack
"
in
response
.
text
assert
"
Open Market Administration
"
in
response
.
text
def
test_base_nav_hides_market_admin_link
(
monkeypatch
):
...
...
tests/routes/test_market_reference_imports.py
View file @
b62c119b
...
...
@@ -2,11 +2,13 @@ import json
import
sys
from
base64
import
b64encode
from
pathlib
import
Path
import
pytest
from
fastapi.responses
import
HTMLResponse
from
fastapi.testclient
import
TestClient
from
itsdangerous
import
TimestampSigner
from
jinja2
import
Environment
,
FileSystemLoader
,
select_autoescape
from
aisbf.models
import
ChatCompletionRequest
from
aisbf.routes.dashboard
import
market
as
dashboard_market
...
...
@@ -165,6 +167,13 @@ class MarketReferenceImportDbStub:
def
get_market_settings
(
self
):
return
dict
(
self
.
market_settings
)
def
get_user_by_id
(
self
,
user_id
):
if
user_id
==
11
:
return
{
"id"
:
11
,
"username"
:
"buyer"
}
if
user_id
==
7
:
return
{
"id"
:
7
,
"username"
:
"seller"
}
return
None
def
get_market_listing
(
self
,
listing_id
):
listings
=
{
self
.
listing
[
"id"
]:
self
.
listing
,
...
...
@@ -243,6 +252,43 @@ class RegistryStub:
return
self
.
_db
class
RuntimeUserHandlerStub
:
def
__init__
(
self
):
self
.
calls
=
[]
self
.
user_providers
=
{}
self
.
rotations
=
{}
self
.
autoselects
=
{}
self
.
user_autoselects
=
{}
async
def
handle_chat_completion
(
self
,
request
,
provider_id
,
body_dict
):
self
.
calls
.
append
((
"provider"
,
provider_id
,
body_dict
))
return
{
"ok"
:
True
,
"provider_id"
:
provider_id
,
"model"
:
body_dict
.
get
(
"model"
)}
async
def
handle_rotation_request
(
self
,
rotation_id
,
body_dict
,
user_id
,
token_id
):
self
.
calls
.
append
((
"rotation"
,
rotation_id
,
body_dict
,
user_id
,
token_id
))
return
{
"ok"
:
True
,
"rotation_id"
:
rotation_id
}
async
def
handle_autoselect_request
(
self
,
autoselect_id
,
body_dict
,
user_id
,
token_id
):
self
.
calls
.
append
((
"autoselect"
,
autoselect_id
,
body_dict
,
user_id
,
token_id
))
return
{
"ok"
:
True
,
"autoselect_id"
:
autoselect_id
}
class
MarketReferenceRuntimeDbStub
(
MarketReferenceImportDbStub
):
def
admin_set_market_listing_active
(
self
,
listing_id
,
is_active
):
listing
=
self
.
get_market_listing
(
listing_id
)
if
not
listing
:
return
False
if
listing_id
==
self
.
listing
[
"id"
]:
self
.
listing
[
"is_active"
]
=
bool
(
is_active
)
elif
listing_id
==
self
.
rotation_listing
[
"id"
]:
self
.
rotation_listing
[
"is_active"
]
=
bool
(
is_active
)
elif
listing_id
==
self
.
model_listing
[
"id"
]:
self
.
model_listing
[
"is_active"
]
=
bool
(
is_active
)
elif
listing_id
==
self
.
autoselect_listing
[
"id"
]:
self
.
autoselect_listing
[
"is_active"
]
=
bool
(
is_active
)
return
True
def
_find_session_secret
()
->
str
:
for
middleware
in
app
.
user_middleware
:
kwargs
=
getattr
(
middleware
,
"kwargs"
,
{})
...
...
@@ -272,6 +318,155 @@ def _login_as_user(client: TestClient, user_id: int = 11) -> None:
)
def
_login_user_api_request
(
client
:
TestClient
,
username
:
str
=
"buyer"
,
user_id
:
int
=
11
)
->
None
:
_set_session_cookie
(
client
,
{
"logged_in"
:
True
,
"username"
:
username
,
"role"
:
"user"
,
"user_id"
:
user_id
,
"expires_at"
:
4102444800
,
},
)
@
pytest
.
fixture
def
runtime_fixture
(
monkeypatch
):
db
=
MarketReferenceRuntimeDbStub
()
reference_id
=
db
.
create_market_import_reference
(
user_id
=
11
,
listing_id
=
db
.
listing
[
"id"
],
reference_type
=
"provider"
,
display_name
=
db
.
listing
[
"title"
],
owner_username
=
db
.
listing
[
"owner_username"
],
source_type
=
db
.
listing
[
"source_type"
],
source_id
=
db
.
listing
[
"source_id"
],
)
monkeypatch
.
setattr
(
dashboard_market
,
"DatabaseRegistry"
,
RegistryStub
(
db
))
return
{
"db"
:
db
,
"handler"
:
dashboard_market
,
"reference_id"
:
reference_id
,
"buyer_user_id"
:
11
,
"listing_id"
:
db
.
listing
[
"id"
],
"seller_user_id"
:
db
.
listing
[
"owner_user_id"
],
}
@
pytest
.
mark
.
asyncio
async
def
test_market_reference_resolves_to_source_listing_at_runtime
(
runtime_fixture
):
handler
=
runtime_fixture
[
"handler"
]
resolved
=
await
handler
.
resolve_market_reference
(
runtime_fixture
[
"reference_id"
],
runtime_fixture
[
"buyer_user_id"
])
assert
resolved
[
"listing_id"
]
==
runtime_fixture
[
"listing_id"
]
assert
resolved
[
"owner_user_id"
]
==
runtime_fixture
[
"seller_user_id"
]
assert
resolved
[
"source_id"
]
==
"seller-provider"
@
pytest
.
mark
.
asyncio
async
def
test_market_reference_rejects_disabled_listing
(
runtime_fixture
):
runtime_fixture
[
"db"
]
.
admin_set_market_listing_active
(
runtime_fixture
[
"listing_id"
],
False
)
handler
=
runtime_fixture
[
"handler"
]
with
pytest
.
raises
(
ValueError
,
match
=
"unavailable"
):
await
handler
.
resolve_market_reference
(
runtime_fixture
[
"reference_id"
],
runtime_fixture
[
"buyer_user_id"
])
class
DirectRequestStub
:
def
__init__
(
self
,
user_id
:
int
):
self
.
state
=
type
(
"State"
,
(),
{})()
self
.
state
.
user_id
=
user_id
self
.
state
.
is_admin
=
False
self
.
state
.
is_global_token
=
False
self
.
state
.
token_id
=
None
@
pytest
.
mark
.
asyncio
async
def
test_user_provider_market_reference_executes_via_seller_handler
(
monkeypatch
):
db
=
MarketReferenceRuntimeDbStub
()
buyer_handler
=
RuntimeUserHandlerStub
()
seller_handler
=
RuntimeUserHandlerStub
()
reference_id
=
db
.
create_market_import_reference
(
user_id
=
11
,
listing_id
=
db
.
listing
[
"id"
],
reference_type
=
"provider"
,
display_name
=
db
.
listing
[
"title"
],
owner_username
=
db
.
listing
[
"owner_username"
],
source_type
=
db
.
listing
[
"source_type"
],
source_id
=
db
.
listing
[
"source_id"
],
)
monkeypatch
.
setattr
(
dashboard_market
,
"DatabaseRegistry"
,
RegistryStub
(
db
))
from
aisbf.routes
import
user_api
monkeypatch
.
setattr
(
user_api
,
"DatabaseRegistry"
,
RegistryStub
(
db
))
def
fake_get_user_handler
(
kind
,
user_id
=
None
):
if
kind
==
"request"
and
user_id
in
(
None
,
11
):
buyer_handler
.
user_providers
=
{
f
"market-ref:{reference_id}"
:
{
"market_reference"
:
True
}}
return
buyer_handler
if
kind
==
"request"
and
user_id
==
7
:
return
seller_handler
raise
AssertionError
((
kind
,
user_id
))
monkeypatch
.
setattr
(
user_api
,
"_get_user_handler"
,
fake_get_user_handler
)
result
=
await
user_api
.
user_chat_completions
(
DirectRequestStub
(
11
),
"buyer"
,
ChatCompletionRequest
(
model
=
f
"user-provider/market-ref:{reference_id}"
,
messages
=
[{
"role"
:
"user"
,
"content"
:
"hi"
}]),
)
assert
result
[
"provider_id"
]
==
"seller-provider"
assert
len
(
seller_handler
.
calls
)
==
1
call_kind
,
provider_id
,
payload
=
seller_handler
.
calls
[
0
]
assert
call_kind
==
"provider"
assert
provider_id
==
"seller-provider"
assert
payload
[
"model"
]
==
"seller-provider"
assert
payload
[
"messages"
][
0
][
"content"
]
==
"hi"
@
pytest
.
mark
.
asyncio
async
def
test_user_provider_market_reference_rejects_unavailable_listing_at_runtime
(
monkeypatch
):
db
=
MarketReferenceRuntimeDbStub
()
buyer_handler
=
RuntimeUserHandlerStub
()
reference_id
=
db
.
create_market_import_reference
(
user_id
=
11
,
listing_id
=
db
.
listing
[
"id"
],
reference_type
=
"provider"
,
display_name
=
db
.
listing
[
"title"
],
owner_username
=
db
.
listing
[
"owner_username"
],
source_type
=
db
.
listing
[
"source_type"
],
source_id
=
db
.
listing
[
"source_id"
],
)
db
.
admin_set_market_listing_active
(
db
.
listing
[
"id"
],
False
)
monkeypatch
.
setattr
(
dashboard_market
,
"DatabaseRegistry"
,
RegistryStub
(
db
))
from
aisbf.routes
import
user_api
monkeypatch
.
setattr
(
user_api
,
"DatabaseRegistry"
,
RegistryStub
(
db
))
def
fake_get_user_handler
(
kind
,
user_id
=
None
):
if
kind
==
"request"
and
user_id
in
(
None
,
11
):
buyer_handler
.
user_providers
=
{
f
"market-ref:{reference_id}"
:
{
"market_reference"
:
True
}}
return
buyer_handler
raise
AssertionError
((
kind
,
user_id
))
monkeypatch
.
setattr
(
user_api
,
"_get_user_handler"
,
fake_get_user_handler
)
with
pytest
.
raises
(
Exception
)
as
exc_info
:
await
user_api
.
user_chat_completions
(
DirectRequestStub
(
11
),
"buyer"
,
ChatCompletionRequest
(
model
=
f
"user-provider/market-ref:{reference_id}"
,
messages
=
[{
"role"
:
"user"
,
"content"
:
"hi"
}]),
)
assert
exc_info
.
value
.
status_code
==
400
assert
exc_info
.
value
.
detail
==
"Market reference unavailable"
def
_seed_dashboard_market_reference_mix
(
db
:
MarketReferenceImportDbStub
)
->
None
:
provider_reference
=
{
"id"
:
1
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment