@@ -828,6 +828,43 @@ async def get_terminal_cwd(
828828 return None
829829
830830
831+ async def get_terminal_system_prompt (
832+ base_url : str ,
833+ headers : dict ,
834+ cookies : Optional [dict ] = None ,
835+ ) -> Optional [str ]:
836+ """Fetch the system prompt from a terminal server.
837+
838+ Checks ``/api/config`` for the ``system`` feature flag first;
839+ only fetches ``/system`` if the flag is present. Returns *None*
840+ silently when the server doesn't support the endpoint.
841+ """
842+ base = base_url .rstrip ('/' )
843+ try :
844+ async with aiohttp .ClientSession (
845+ timeout = aiohttp .ClientTimeout (total = 3 ),
846+ trust_env = True ,
847+ ) as session :
848+ # 1. Check feature flag
849+ async with session .get (f'{ base } /api/config' ) as resp :
850+ if resp .status != 200 :
851+ return None
852+ config = await resp .json ()
853+ if not config .get ('features' , {}).get ('system' ):
854+ return None
855+
856+ # 2. Fetch system prompt
857+ async with session .get (
858+ f'{ base } /system' , headers = headers , cookies = cookies or {}
859+ ) as resp :
860+ if resp .status == 200 :
861+ data = await resp .json ()
862+ return data .get ('prompt' )
863+ except Exception as e :
864+ log .debug (f'Failed to fetch terminal system prompt: { e } ' )
865+ return None
866+
867+
831868async def set_terminal_servers (request : Request ):
832869 """Load and cache OpenAPI specs from all TERMINAL_SERVER_CONNECTIONS."""
833870 connections = request .app .state .config .TERMINAL_SERVER_CONNECTIONS or []
@@ -867,6 +904,25 @@ async def set_terminal_servers(request: Request):
867904
868905 request .app .state .TERMINAL_SERVERS = await get_tool_servers_data (server_configs )
869906
907+ # Fetch system prompts concurrently (runs at cache time, not per-request)
908+ connections_by_id = {c .get ('id' ): c for c in connections if c .get ('id' )}
909+
910+ async def _fetch_system_prompt (server ):
911+ connection = connections_by_id .get (server .get ('id' ))
912+ if not connection :
913+ return
914+ headers = {}
915+ if connection .get ('auth_type' , 'bearer' ) == 'bearer' :
916+ headers ['Authorization' ] = f'Bearer { connection .get ("key" , "" )} '
917+ prompt = await get_terminal_system_prompt (server ['url' ], headers )
918+ if prompt :
919+ server ['system_prompt' ] = prompt
920+
921+ await asyncio .gather (
922+ * [_fetch_system_prompt (s ) for s in request .app .state .TERMINAL_SERVERS ],
923+ return_exceptions = True ,
924+ )
925+
870926 if request .app .state .redis is not None :
871927 await request .app .state .redis .set ('terminal_servers' , json .dumps (request .app .state .TERMINAL_SERVERS ))
872928
@@ -894,7 +950,7 @@ async def get_terminal_tools(
894950 terminal_id : str ,
895951 user : UserModel ,
896952 extra_params : dict ,
897- ) -> dict [str , dict ]:
953+ ) -> tuple [ dict [str , dict ], Optional [ str ] ]:
898954 """Resolve tools for a terminal server identified by terminal_id.
899955
900956 - Finds the connection in TERMINAL_SERVER_CONNECTIONS
@@ -941,14 +997,14 @@ async def get_terminal_tools(
941997 headers ['Authorization' ] = f'Bearer { oauth_token .get ("access_token" , "" )} '
942998 # auth_type == "none": no Authorization header
943999
1000+ system_prompt = server_data .get ('system_prompt' )
9441001 terminal_cwd = await get_terminal_cwd (connection .get ('url' , '' ), headers , cookies )
9451002
9461003 tools_dict = {}
9471004 for spec in specs :
9481005 function_name = spec ['name' ]
949-
950- # Inject CWD into run_command description
9511006 tool_spec = clean_openai_tool_schema (spec )
1007+
9521008 if function_name == 'run_command' and terminal_cwd :
9531009 tool_spec ['description' ] = (
9541010 tool_spec .get ('description' , '' ) + f'\n \n The current working directory is: { terminal_cwd } '
@@ -977,7 +1033,7 @@ async def tool_function(**kwargs):
9771033 'type' : 'terminal' ,
9781034 }
9791035
980- return tools_dict
1036+ return tools_dict , system_prompt
9811037
9821038
9831039async def get_tool_server_data (url : str , headers : Optional [dict ]) -> Dict [str , Any ]:
0 commit comments