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
0f769be0
Commit
0f769be0
authored
May 17, 2026
by
Stefy Lanza (nextime / spora )
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Market and providers show now gpu for coderai provs
parent
c0b75758
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
98 additions
and
3 deletions
+98
-3
coderai_broker.py
aisbf/routes/coderai_broker.py
+7
-1
market.py
aisbf/routes/dashboard/market.py
+26
-0
market.html
templates/dashboard/market.html
+25
-0
providers.html
templates/dashboard/providers.html
+20
-1
user_providers.html
templates/dashboard/user_providers.html
+20
-1
No files found.
aisbf/routes/coderai_broker.py
View file @
0f769be0
...
...
@@ -121,9 +121,15 @@ async def _coderai_broker_websocket_impl(websocket: WebSocket, scope_name: str):
registered_payload
=
_coderai_register_payload
(
session
.
provider_id
,
session
.
client_id
,
username
,
owner_user_id
,
expected_scope
)
registered_payload
.
update
({
"session_id"
:
session
.
session_id
,
"status"
:
"ok"
,
"request_id"
:
first_msg
.
get
(
"request_id"
)})
await
websocket
.
send_text
(
json
.
dumps
(
registered_payload
))
_gpu_names
=
", "
.
join
(
g
.
get
(
"name"
,
"?"
)
for
g
in
(
metadata
.
get
(
"gpus"
)
or
[])
)
or
"none"
logger
.
info
(
"CoderAI broker registered provider=
%
s client=
%
s session_id=
%
s scope=
%
s"
,
"CoderAI broker registered provider=
%
s client=
%
s session_id=
%
s scope=
%
s"
" gpu_count=
%
s gpus=[
%
s] total_vram_mb=
%
s available_vram_mb=
%
s"
,
provider_id
,
client_id
,
session
.
session_id
,
expected_scope
,
metadata
.
get
(
"gpu_count"
),
_gpu_names
,
metadata
.
get
(
"total_vram_mb"
),
metadata
.
get
(
"available_vram_mb"
),
)
# Populate the model cache in the background now that the session is live.
...
...
aisbf/routes/dashboard/market.py
View file @
0f769be0
...
...
@@ -3,6 +3,7 @@ from fastapi.responses import HTMLResponse, JSONResponse
from
aisbf.routes.auth
import
require_dashboard_auth
,
require_api_auth
,
require_admin
from
aisbf.database
import
DatabaseRegistry
from
aisbf.analytics
import
get_analytics
from
aisbf.coderai_broker
import
broker
as
coderai_broker
import
json
import
logging
...
...
@@ -184,6 +185,29 @@ def _build_autoselect_listing_payload(owner_user_id: int, owner_username: str, a
}
async
def
_attach_hardware_snapshot
(
listing
:
dict
)
->
dict
:
"""Attach live broker hardware metadata for coderai listings."""
metadata
=
listing
.
get
(
'metadata'
)
or
{}
if
metadata
.
get
(
'provider_type'
)
!=
'coderai'
:
return
listing
provider_id
=
listing
.
get
(
'provider_id'
)
if
not
provider_id
:
return
listing
try
:
snapshot
=
await
coderai_broker
.
get_session_snapshot
(
provider_id
)
if
snapshot
and
snapshot
.
get
(
'connected'
):
smeta
=
snapshot
.
get
(
'metadata'
)
or
{}
listing
[
'hardware'
]
=
{
'gpu_count'
:
smeta
.
get
(
'gpu_count'
,
0
),
'gpus'
:
smeta
.
get
(
'gpus'
)
or
[],
'total_vram_mb'
:
smeta
.
get
(
'total_vram_mb'
),
'available_vram_mb'
:
smeta
.
get
(
'available_vram_mb'
),
}
except
Exception
:
pass
return
listing
def
_attach_analytics_snapshot
(
listing
:
dict
):
analytics
=
get_analytics
()
source_type
=
listing
.
get
(
'source_type'
)
...
...
@@ -378,6 +402,7 @@ async def dashboard_market(request: Request):
listing_copy
[
'online'
]
=
_listing_online
(
listing_copy
)
owner
=
db
.
get_user_by_id
(
listing
[
'owner_user_id'
])
if
listing
.
get
(
'owner_user_id'
)
else
None
listing_copy
[
'owner_display_name'
]
=
(
owner
or
{})
.
get
(
'display_name'
)
or
listing
.
get
(
'owner_username'
)
await
_attach_hardware_snapshot
(
listing_copy
)
enriched
.
append
(
listing_copy
)
return
_templates
.
TemplateResponse
(
...
...
@@ -477,6 +502,7 @@ async def api_market_listings(request: Request):
for
listing
in
filtered
:
listing
.
pop
(
'_scope_priority'
,
None
)
listing
.
pop
(
'_match_priority'
,
None
)
await
_attach_hardware_snapshot
(
listing
)
return
JSONResponse
({
'listings'
:
filtered
})
...
...
templates/dashboard/market.html
View file @
0f769be0
...
...
@@ -66,6 +66,30 @@ function voteSummary(votes, target) {
return
`+
${
item
.
upvotes
}
/ -
${
item
.
downvotes
}
(score
${
item
.
score
}
)`
;
}
function
formatVramMb
(
value
)
{
if
(
value
==
null
||
value
===
''
)
return
'?'
;
const
mb
=
Number
(
value
);
if
(
!
Number
.
isFinite
(
mb
))
return
'?'
;
if
(
mb
>=
1024
)
return
`
${(
mb
/
1024
).
toFixed
(
1
)}
GB`
;
return
`
${
Math
.
round
(
mb
)}
MB`
;
}
function
renderListingHardware
(
hw
)
{
if
(
!
hw
)
return
''
;
const
gpus
=
Array
.
isArray
(
hw
.
gpus
)
?
hw
.
gpus
:
[];
const
gpuName
=
gpus
[
0
]?.
name
||
null
;
const
total
=
hw
.
total_vram_mb
;
const
free
=
hw
.
available_vram_mb
;
if
(
!
gpuName
&&
total
==
null
)
return
''
;
const
parts
=
[];
if
(
gpuName
)
{
const
short
=
gpuName
.
replace
(
/^NVIDIA
\s
+
(
GeForce
\s
+
)?
/i
,
''
).
replace
(
/^AMD
\s
+
(
Radeon
\s
+RX
\s
+
)?
/i
,
''
);
parts
.
push
(
short
);
}
if
(
total
!=
null
)
parts
.
push
(
`
${
formatVramMb
(
free
)}
/
${
formatVramMb
(
total
)}
VRAM`
);
return
`<div style="font-size:12px;margin-bottom:8px;display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:999px;background:rgba(99,102,241,0.1);border:1px solid rgba(99,102,241,0.3);color:#a5b4fc;">
${
parts
.
join
(
' · '
)}
</div>`
;
}
function
renderMarket
()
{
const
root
=
document
.
getElementById
(
'market-grid'
);
root
.
innerHTML
=
''
;
...
...
@@ -86,6 +110,7 @@ function renderMarket() {
<p style="color: var(--color-text); margin: 12px 0;">
${
listing
.
description
||
''
}
</p>
<div style="font-size:12px; color: var(--color-muted); margin-bottom: 10px;">Provider:
${
listing
.
provider_id
||
'-'
}
${
listing
.
model_id
?
` | Model:
${
listing
.
model_id
}
`
:
''
}
${
listing
.
model_type_label
?
` | Type:
${
listing
.
model_type_label
}
`
:
''
}
${
listing
.
size_label
?
` | Size:
${
listing
.
size_label
}
`
:
''
}
</div>
<div style="font-size:12px; color: var(--color-muted); margin-bottom: 10px;">Status:
${
listing
.
online
?
'online'
:
'offline'
}${(
listing
.
capabilities
||
[]).
length
?
` | Capabilities:
${(
listing
.
capabilities
||
[]).
join
(
', '
)}
`
:
''
}
</div>
${
renderListingHardware
(
listing
.
hardware
)}
<div style="display:grid; grid-template-columns:1fr 1fr; gap:6px; font-size:12px; margin-bottom:12px;">
<div>Listing votes:
${
voteSummary
(
listing
.
votes
,
'listing'
)}
</div>
<div>User votes:
${
voteSummary
(
listing
.
votes
,
'user'
)}
</div>
...
...
templates/dashboard/providers.html
View file @
0f769be0
...
...
@@ -200,7 +200,26 @@ function renderCoderaiCollapsedStatus(provider) {
const
bg
=
connected
?
'rgba(34,197,94,0.16)'
:
'rgba(239,68,68,0.16)'
;
const
border
=
connected
?
'rgba(34,197,94,0.45)'
:
'rgba(239,68,68,0.45)'
;
const
color
=
connected
?
'#22c55e'
:
'#ef4444'
;
return
`<span style="display:inline-flex;align-items:center;gap:6px;padding:3px 9px;border-radius:999px;font-size:12px;font-weight:600;background:
${
bg
}
;border:1px solid
${
border
}
;color:
${
color
}
;"><span style="width:8px;height:8px;border-radius:50%;background:
${
color
}
;display:inline-block;"></span>
${
label
}
</span>`
;
const
statusBadge
=
`<span style="display:inline-flex;align-items:center;gap:6px;padding:3px 9px;border-radius:999px;font-size:12px;font-weight:600;background:
${
bg
}
;border:1px solid
${
border
}
;color:
${
color
}
;"><span style="width:8px;height:8px;border-radius:50%;background:
${
color
}
;display:inline-block;"></span>
${
label
}
</span>`
;
if
(
!
connected
)
return
statusBadge
;
const
meta
=
coderaiConfig
.
broker_session
?.
metadata
||
{};
return
statusBadge
+
renderCoderaiHardwareChip
(
meta
);
}
function
renderCoderaiHardwareChip
(
meta
)
{
const
gpus
=
Array
.
isArray
(
meta
?.
gpus
)
?
meta
.
gpus
:
[];
const
gpuName
=
gpus
[
0
]?.
name
||
null
;
const
totalVram
=
meta
?.
total_vram_mb
;
const
freeVram
=
meta
?.
available_vram_mb
;
if
(
!
gpuName
&&
totalVram
==
null
)
return
''
;
const
parts
=
[];
if
(
gpuName
)
{
const
shortName
=
gpuName
.
replace
(
/^NVIDIA
\s
+
(
GeForce
\s
+
)?
/i
,
''
).
replace
(
/^AMD
\s
+
(
Radeon
\s
+RX
\s
+
)?
/i
,
''
);
parts
.
push
(
shortName
);
}
if
(
totalVram
!=
null
)
parts
.
push
(
`
${
formatVramMb
(
freeVram
)}
/
${
formatVramMb
(
totalVram
)}
`
);
if
(
!
parts
.
length
)
return
''
;
return
`<span style="display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:999px;font-size:12px;background:rgba(99,102,241,0.12);border:1px solid rgba(99,102,241,0.35);color:#a5b4fc;margin-left:4px;">
${
parts
.
join
(
' · '
)}
</span>`
;
}
function
formatRunpodTimestamp
(
value
)
{
...
...
templates/dashboard/user_providers.html
View file @
0f769be0
...
...
@@ -196,7 +196,26 @@ function renderCoderaiCollapsedStatus(provider) {
const
bg
=
connected
?
'rgba(34,197,94,0.16)'
:
'rgba(239,68,68,0.16)'
;
const
border
=
connected
?
'rgba(34,197,94,0.45)'
:
'rgba(239,68,68,0.45)'
;
const
color
=
connected
?
'#22c55e'
:
'#ef4444'
;
return
`<span style="display:inline-flex;align-items:center;gap:6px;padding:3px 9px;border-radius:999px;font-size:12px;font-weight:600;background:
${
bg
}
;border:1px solid
${
border
}
;color:
${
color
}
;"><span style="width:8px;height:8px;border-radius:50%;background:
${
color
}
;display:inline-block;"></span>
${
label
}
</span>`
;
const
statusBadge
=
`<span style="display:inline-flex;align-items:center;gap:6px;padding:3px 9px;border-radius:999px;font-size:12px;font-weight:600;background:
${
bg
}
;border:1px solid
${
border
}
;color:
${
color
}
;"><span style="width:8px;height:8px;border-radius:50%;background:
${
color
}
;display:inline-block;"></span>
${
label
}
</span>`
;
if
(
!
connected
)
return
statusBadge
;
const
meta
=
coderaiConfig
.
broker_session
?.
metadata
||
{};
return
statusBadge
+
renderCoderaiHardwareChip
(
meta
);
}
function
renderCoderaiHardwareChip
(
meta
)
{
const
gpus
=
Array
.
isArray
(
meta
?.
gpus
)
?
meta
.
gpus
:
[];
const
gpuName
=
gpus
[
0
]?.
name
||
null
;
const
totalVram
=
meta
?.
total_vram_mb
;
const
freeVram
=
meta
?.
available_vram_mb
;
if
(
!
gpuName
&&
totalVram
==
null
)
return
''
;
const
parts
=
[];
if
(
gpuName
)
{
const
shortName
=
gpuName
.
replace
(
/^NVIDIA
\s
+
(
GeForce
\s
+
)?
/i
,
''
).
replace
(
/^AMD
\s
+
(
Radeon
\s
+RX
\s
+
)?
/i
,
''
);
parts
.
push
(
shortName
);
}
if
(
totalVram
!=
null
)
parts
.
push
(
`
${
formatVramMb
(
freeVram
)}
/
${
formatVramMb
(
totalVram
)}
`
);
if
(
!
parts
.
length
)
return
''
;
return
`<span style="display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:999px;font-size:12px;background:rgba(99,102,241,0.12);border:1px solid rgba(99,102,241,0.35);color:#a5b4fc;margin-left:4px;">
${
parts
.
join
(
' · '
)}
</span>`
;
}
function
renderGpuSummary
(
metadata
)
{
...
...
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