Skip to content

Commit 03bbb8c

Browse files
committed
fix: sub-app works with dev-ui
1 parent 108b727 commit 03bbb8c

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

src/google/adk/cli/adk_web_server.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from contextlib import asynccontextmanager
1919
import logging
2020
import os
21+
from pathlib import Path
2122
import time
2223
import traceback
2324
import typing
@@ -31,6 +32,7 @@
3132
from fastapi import HTTPException
3233
from fastapi import Query
3334
from fastapi.middleware.cors import CORSMiddleware
35+
from fastapi.responses import JSONResponse
3436
from fastapi.responses import RedirectResponse
3537
from fastapi.responses import StreamingResponse
3638
from fastapi.staticfiles import StaticFiles
@@ -44,6 +46,7 @@
4446
from opentelemetry.sdk.trace import TracerProvider
4547
from pydantic import Field
4648
from pydantic import ValidationError
49+
from starlette.responses import Response
4750
from starlette.types import Lifespan
4851
from typing_extensions import override
4952
from watchdog.observers import Observer
@@ -193,6 +196,28 @@ class GetEventGraphResult(common.BaseModel):
193196
dot_src: str
194197

195198

199+
class ConfigInjectingStaticFiles(StaticFiles):
200+
"""
201+
Custom StaticFiles that injects config.json for dev-ui.
202+
Fixes https://github.com/google/adk-python/issues/2072
203+
"""
204+
205+
def __init__(self, *, directory, base_url: Optional[str], **kwargs):
206+
super().__init__(directory=directory, **kwargs)
207+
if base_url is None:
208+
base_url = ""
209+
self.base_url = base_url
210+
211+
async def get_response(self, path: str, scope) -> Response:
212+
# Check if the request is for config.json
213+
if Path(path).as_posix() == "assets/config/runtime-config.json":
214+
config = {"backendUrl": self.base_url}
215+
return JSONResponse(content=config)
216+
217+
# Otherwise, serve static files normally
218+
return await super().get_response(path, scope)
219+
220+
196221
class AdkWebServer:
197222
"""Helper class for setting up and running the ADK web server on FastAPI.
198223
@@ -284,6 +309,7 @@ def get_fast_api_app(
284309
[Observer, "AdkWebServer"], None
285310
] = lambda o, s: None,
286311
register_processors: Callable[[TracerProvider], None] = lambda o: None,
312+
base_url: Optional[str] = None,
287313
):
288314
"""Creates a FastAPI app for the ADK web server.
289315
@@ -300,6 +326,8 @@ def get_fast_api_app(
300326
tear_down_observer: Callback for cleaning up the file system observer.
301327
register_processors: Callback for additional Span processors to be added
302328
to the TracerProvider.
329+
base_url: The base URL for the web-ui, useful if fastapi app is mounted as
330+
a sub-application. If none is provided, the host is used in the frontend.
303331
304332
Returns:
305333
A FastAPI app instance.
@@ -996,7 +1024,12 @@ async def redirect_dev_ui_add_slash():
9961024

9971025
app.mount(
9981026
"/dev-ui/",
999-
StaticFiles(directory=web_assets_dir, html=True, follow_symlink=True),
1027+
ConfigInjectingStaticFiles(
1028+
directory=web_assets_dir,
1029+
base_url=base_url,
1030+
html=True,
1031+
follow_symlink=True,
1032+
),
10001033
name="static",
10011034
)
10021035

src/google/adk/cli/fast_api.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@
2727
from fastapi import FastAPI
2828
from fastapi import UploadFile
2929
from fastapi.responses import FileResponse
30+
from fastapi.responses import JSONResponse
3031
from fastapi.responses import PlainTextResponse
32+
from fastapi.staticfiles import StaticFiles
3133
from opentelemetry.sdk.trace import export
3234
from opentelemetry.sdk.trace import TracerProvider
35+
from starlette.responses import Response
3336
from starlette.types import Lifespan
3437
from watchdog.observers import Observer
3538

0 commit comments

Comments
 (0)