diff --git a/gptscript/gptscript.py b/gptscript/gptscript.py index cbd2cdf..d7891a8 100644 --- a/gptscript/gptscript.py +++ b/gptscript/gptscript.py @@ -3,11 +3,8 @@ import platform from subprocess import Popen, PIPE from sys import executable -from time import sleep from typing import Any, Callable, Awaitable, List -import requests - from gptscript.confirm import AuthResponse from gptscript.credentials import Credential, to_credential from gptscript.frame import RunFrame, CallFrame, PromptFrame, Program @@ -22,25 +19,23 @@ class GPTScript: __gptscript_count = 0 __server_url = "" __process: Popen = None - __server_ready: bool = False def __init__(self, opts: GlobalOptions = None): if opts is None: opts = GlobalOptions() self.opts = opts + start_sdk = GPTScript.__process is None and GPTScript.__server_url == "" and self.opts.URL == "" GPTScript.__gptscript_count += 1 - if GPTScript.__server_url == "": - GPTScript.__server_url = os.environ.get("GPTSCRIPT_URL", "http://127.0.0.1:0") - if not (GPTScript.__server_url.startswith("http://") or GPTScript.__server_url.startswith("https://")): - GPTScript.__server_url = f"http://{GPTScript.__server_url}" + GPTScript.__server_url = os.environ.get("GPTSCRIPT_URL", "") + start_sdk = start_sdk and GPTScript.__server_url == "" - if GPTScript.__gptscript_count == 1 and os.environ.get("GPTSCRIPT_URL", "") == "": + if start_sdk: self.opts.toEnv() GPTScript.__process = Popen( - [_get_command(), "--listen-address", GPTScript.__server_url.removeprefix("http://"), "sdkserver"], + [_get_command(), "sys.sdkserver", "--listen-address", "127.0.0.1:0"], stdin=PIPE, stdout=PIPE, stderr=PIPE, @@ -53,35 +48,25 @@ def __init__(self, opts: GlobalOptions = None): if "=" in GPTScript.__server_url: GPTScript.__server_url = GPTScript.__server_url.split("=")[1] - self.opts.Env.append("GPTSCRIPT_URL=" + GPTScript.__server_url) - self._server_url = GPTScript.__server_url - if not (self._server_url.startswith("http://") or self._server_url.startswith("https://")): - self._server_url = f"http://{self._server_url}" - self._wait_for_gptscript() - - def _wait_for_gptscript(self): - if not GPTScript.__server_ready: - for _ in range(0, 20): - try: - resp = requests.get(self._server_url + "/healthz") - if resp.status_code == 200: - GPTScript.__server_ready = True - return - except requests.exceptions.ConnectionError: - pass + if self.opts.URL == "": + self.opts.URL = GPTScript.__server_url + if not (self.opts.URL.startswith("http://") or self.opts.URL.startswith("https://")): + self.opts.URL = f"http://{self.opts.URL}" - sleep(1) + self.opts.Env.append("GPTSCRIPT_URL=" + self.opts.URL) - raise Exception("Failed to start gptscript") + if self.opts.Token == "": + self.opts.Token = os.environ.get("GPTSCRIPT_TOKEN", "") + if self.opts.Token != "": + self.opts.Env.append("GPTSCRIPT_TOKEN=" + self.opts.Token) def close(self): GPTScript.__gptscript_count -= 1 if GPTScript.__gptscript_count == 0 and GPTScript.__process is not None: GPTScript.__process.stdin.close() GPTScript.__process.wait() - GPTScript.__server_ready = False GPTScript.__process = None - self._server_url = "" + self.opts = None def evaluate( self, @@ -94,7 +79,6 @@ def evaluate( "evaluate", tool, opts.merge_global_opts(self.opts), - self._server_url, event_handlers=event_handlers, ).next_chat(opts.input) @@ -108,7 +92,6 @@ def run( "run", tool_path, opts.merge_global_opts(self.opts), - self._server_url, event_handlers=event_handlers, ).next_chat(opts.input) @@ -165,7 +148,7 @@ async def prompt(self, resp: PromptResponse): await self._run_basic_command("prompt-response/" + resp.id, resp.responses) async def _run_basic_command(self, sub_command: str, request_body: Any = None): - run = RunBasicCommand(sub_command, request_body, self._server_url) + run = RunBasicCommand(sub_command, request_body, self.opts.URL, self.opts.Token) run.next_chat() diff --git a/gptscript/opts.py b/gptscript/opts.py index c44954e..717541c 100644 --- a/gptscript/opts.py +++ b/gptscript/opts.py @@ -5,6 +5,8 @@ class GlobalOptions: def __init__( self, + url: str = "", + token: str = "", apiKey: str = "", baseURL: str = "", defaultModelProvider: str = "", @@ -12,6 +14,8 @@ def __init__( cacheDir: str = "", env: Mapping[str, str] = None, ): + self.URL = url + self.Token = token self.APIKey = apiKey self.BaseURL = baseURL self.DefaultModel = defaultModel @@ -25,7 +29,9 @@ def __init__( def merge(self, other: Self) -> Self: cp = self.__class__() if other is None: - return cp + return self + cp.URL = other.URL if other.URL != "" else self.URL + cp.Token = other.Token if other.Token != "" else self.Token cp.APIKey = other.APIKey if other.APIKey != "" else self.APIKey cp.BaseURL = other.BaseURL if other.BaseURL != "" else self.BaseURL cp.DefaultModel = other.DefaultModel if other.DefaultModel != "" else self.DefaultModel @@ -62,13 +68,15 @@ def __init__(self, location: str = "", env: list[str] = None, forceSequential: bool = False, + url: str = "", + token: str = "", apiKey: str = "", baseURL: str = "", defaultModelProvider: str = "", defaultModel: str = "", cacheDir: str = "", ): - super().__init__(apiKey, baseURL, defaultModelProvider, defaultModel, cacheDir) + super().__init__(url, token, apiKey, baseURL, defaultModelProvider, defaultModel, cacheDir) self.input = input self.disableCache = disableCache self.subTool = subTool diff --git a/gptscript/run.py b/gptscript/run.py index b9a2076..e4f09e8 100644 --- a/gptscript/run.py +++ b/gptscript/run.py @@ -10,11 +10,10 @@ class Run: - def __init__(self, subCommand: str, tools: Union[ToolDef | list[ToolDef] | str], opts: Options, gptscriptURL: str, + def __init__(self, subCommand: str, tools: Union[ToolDef | list[ToolDef] | str], opts: Options, event_handlers: list[Callable[[Self, CallFrame | RunFrame | PromptFrame], Awaitable[None]]] = None): self.requestPath = subCommand self.tools = tools - self.gptscriptURL = gptscriptURL self.event_handlers = event_handlers self.opts = opts if self.opts is None: @@ -78,8 +77,7 @@ def next_chat(self, input: str = "") -> Self: run = self if run.state != RunState.Creating: - run = type(self)(self.requestPath, self.tools, self.opts, self.gptscriptURL, - event_handlers=self.event_handlers) + run = type(self)(self.requestPath, self.tools, self.opts, event_handlers=self.event_handlers) if self.chatState and self._state == RunState.Continue: # Only update the chat state if the previous run didn't error. @@ -120,7 +118,16 @@ async def _request(self, tool: Any): async with httpx.AsyncClient(timeout=httpx.Timeout(15 * 60.0)) as client: method = "GET" if tool is None else "POST" - async with client.stream(method, self.gptscriptURL + "/" + self.requestPath, json=tool) as resp: + headers = None + if self.opts.Token: + headers = {"Authorization": f"Bearer {self.opts.Token}"} + + async with client.stream( + method, + self.opts.URL + "/" + self.requestPath, + json=tool, + headers=headers, + ) as resp: self._resp = resp self._state = RunState.Running done = True @@ -203,8 +210,8 @@ async def aclose(self): class RunBasicCommand(Run): - def __init__(self, subCommand: str, request_body: Any, gptscriptURL: str): - super().__init__(subCommand, "", Options(), gptscriptURL) + def __init__(self, subCommand: str, request_body: Any, gptscriptURL: str, gptscriptToken: str): + super().__init__(subCommand, "", Options(url=gptscriptURL, token=gptscriptToken)) self.request_body = request_body def next_chat(self, input: str = "") -> Self: