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
fd742959
Commit
fd742959
authored
May 19, 2026
by
Stefy Lanza (nextime / spora )
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix coderai routing
parent
403b9bf3
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
85 additions
and
6 deletions
+85
-6
coderai.py
aisbf/providers/coderai.py
+8
-6
admin.py
aisbf/routes/dashboard/admin.py
+77
-0
No files found.
aisbf/providers/coderai.py
View file @
fd742959
...
...
@@ -197,14 +197,16 @@ class CoderAIProviderHandler(BaseProviderHandler):
return
False
if
self
.
_broker_mode
:
return
True
if
not
self
.
_broker_preferred
:
return
False
session
=
await
coderai_broker
.
get_session
(
self
.
provider_id
,
self
.
_client_id
)
if
session
is
None
:
# Use get_session_snapshot() so clustered deployments are handled correctly:
# the session may live on a different node; send_request() routes via the
# shared-cache queue in that case — no direct HTTP fallback needed.
snapshot
=
await
coderai_broker
.
get_session_snapshot
(
self
.
provider_id
,
self
.
_client_id
)
if
not
snapshot
or
not
snapshot
.
get
(
"connected"
):
return
False
meta
=
snapshot
.
get
(
"metadata"
)
or
{}
if
self
.
user_id
is
None
:
return
session
.
metada
ta
.
get
(
"owner_user_id"
)
is
None
return
session
.
metada
ta
.
get
(
"owner_user_id"
)
==
self
.
user_id
return
me
ta
.
get
(
"owner_user_id"
)
is
None
return
me
ta
.
get
(
"owner_user_id"
)
==
self
.
user_id
async
def
_broker_request
(
self
,
op
:
str
,
payload
:
Dict
[
str
,
Any
],
timeout
:
float
)
->
Dict
[
str
,
Any
]:
extra
=
{}
...
...
aisbf/routes/dashboard/admin.py
View file @
fd742959
...
...
@@ -2798,3 +2798,80 @@ async def dashboard_studio_audio_speech(request: Request):
async
def
dashboard_user_studio_audio_speech
(
request
:
Request
,
username
:
str
):
scope
,
user_id
=
_dashboard_studio_user_scope
(
request
,
username
)
return
await
_studio_audio_speech
(
request
,
user_id
=
user_id
)
async
def
_studio_any_dispatch
(
request
:
Request
,
path
:
str
,
user_id
:
Optional
[
int
]):
"""Generic dispatcher for any studio path.
Provider resolution order:
1. ?provider=<provider_id> query param (works for any path including admin/static)
2. model field in JSON body as 'provider_id/model_name' (works for v1/ endpoints)
This is the catch-all for paths not handled by more specific studio routes.
"""
from
aisbf.handlers
import
RequestHandler
,
RotationHandler
,
AutoselectHandler
method
=
request
.
method
provider_id
=
request
.
query_params
.
get
(
"provider"
,
""
)
.
strip
()
try
:
body
=
await
request
.
json
()
body
=
dict
(
body
)
except
Exception
:
body
=
{}
if
not
provider_id
:
model_str
=
_studio_normalize_model
(
path
,
body
)
if
model_str
:
kind
,
source_id
,
target_id
=
_parse_studio_model_id
(
model_str
)
if
kind
==
'rotation'
:
rot
=
RotationHandler
(
user_id
=
user_id
)
if
not
hasattr
(
rot
,
'_select_provider_and_model'
):
raise
HTTPException
(
status_code
=
400
,
detail
=
f
"Rotation '{source_id}' cannot be resolved for this endpoint"
)
provider_id
,
actual_model
=
rot
.
_select_provider_and_model
(
source_id
)
body
[
'model'
]
=
actual_model
elif
kind
==
'autoselect'
:
asel_cfg
=
(
_config
.
autoselect
or
{})
.
get
(
source_id
)
if
_config
else
None
if
not
asel_cfg
:
asel
=
AutoselectHandler
(
user_id
=
user_id
)
asel_cfg
=
getattr
(
asel
,
'user_autoselects'
,
{})
.
get
(
source_id
)
if
not
asel_cfg
:
raise
HTTPException
(
status_code
=
404
,
detail
=
f
"Autoselect '{source_id}' not found"
)
fallback
=
getattr
(
asel_cfg
,
'fallback'
,
None
)
or
(
asel_cfg
.
get
(
'fallback'
)
if
isinstance
(
asel_cfg
,
dict
)
else
''
)
or
''
if
'/'
in
fallback
:
provider_id
,
actual_model
=
fallback
.
split
(
'/'
,
1
)
body
[
'model'
]
=
actual_model
else
:
raise
HTTPException
(
status_code
=
400
,
detail
=
f
"Cannot resolve autoselect '{source_id}' for non-chat endpoint"
)
elif
kind
==
'provider'
:
provider_id
=
source_id
body
[
'model'
]
=
target_id
if
not
provider_id
:
return
JSONResponse
(
{
"error"
:
"provider required: use ?provider=<provider_id> or include model as 'provider_id/model_name' in the request body"
},
status_code
=
400
,
)
handler
=
RequestHandler
(
user_id
=
user_id
)
return
await
handler
.
handle_generic_proxy
(
request
,
provider_id
,
path
,
body
,
method
=
method
)
@
router
.
api_route
(
"/dashboard/api/studio/{path:path}"
,
methods
=
[
"GET"
,
"POST"
,
"PUT"
,
"DELETE"
,
"PATCH"
],
)
async
def
dashboard_studio_any_proxy
(
request
:
Request
,
path
:
str
):
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
return
await
_studio_any_dispatch
(
request
,
path
,
user_id
=
None
)
@
router
.
api_route
(
"/dashboard/api/studio/u/{username}/{path:path}"
,
methods
=
[
"GET"
,
"POST"
,
"PUT"
,
"DELETE"
,
"PATCH"
],
)
async
def
dashboard_user_studio_any_proxy
(
request
:
Request
,
username
:
str
,
path
:
str
):
scope
,
user_id
=
_dashboard_studio_user_scope
(
request
,
username
)
return
await
_studio_any_dispatch
(
request
,
path
,
user_id
=
user_id
)
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