langchain-githubcopilot-chat 0.5.0__tar.gz → 0.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langchain-githubcopilot-chat
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: An integration package connecting GithubcopilotChat and LangChain
5
5
  Home-page: https://github.com/langchain-ai/langchain
6
6
  License: MIT
@@ -721,24 +721,46 @@ class ChatGithubCopilot(BaseChatModel):
721
721
  def _do_stream(self, payload: Dict[str, Any]) -> Iterator[Dict[str, Any]]:
722
722
  """Perform a synchronous streaming HTTP POST and yield parsed SSE chunks."""
723
723
  headers = self._build_headers()
724
- with httpx.stream(
725
- "POST",
726
- self._inference_url,
727
- headers=headers,
728
- json=payload,
729
- timeout=self.timeout,
730
- ) as response:
731
- response.raise_for_status()
732
- for line in response.iter_lines():
733
- line = line.strip()
734
- if not line or line == "data: [DONE]":
735
- continue
736
- if line.startswith("data: "):
737
- line = line[len("data: ") :]
738
- try:
739
- yield json.loads(line)
740
- except json.JSONDecodeError:
741
- continue
724
+ last_exc: Optional[Exception] = None
725
+ for attempt in range(self.max_retries + 1):
726
+ try:
727
+ with httpx.stream(
728
+ "POST",
729
+ self._inference_url,
730
+ headers=headers,
731
+ json=payload,
732
+ timeout=self.timeout,
733
+ ) as response:
734
+ if response.status_code == 401:
735
+ self._refresh_token_sync()
736
+ headers = self._build_headers()
737
+ raise httpx.TransportError("401 — token refreshed, retrying")
738
+ response.raise_for_status()
739
+ for line in response.iter_lines():
740
+ line = line.strip()
741
+ if not line or line == "data: [DONE]":
742
+ continue
743
+ if line.startswith("data: "):
744
+ line = line[len("data: ") :]
745
+ try:
746
+ yield json.loads(line)
747
+ except json.JSONDecodeError:
748
+ continue
749
+ return
750
+ except (httpx.TimeoutException, httpx.TransportError) as exc:
751
+ last_exc = exc
752
+ if attempt == self.max_retries:
753
+ raise
754
+ except httpx.HTTPStatusError as exc:
755
+ if exc.response.status_code < 500:
756
+ raise
757
+ last_exc = exc
758
+ if attempt == self.max_retries:
759
+ raise
760
+ if attempt < self.max_retries:
761
+ backoff = 2**attempt
762
+ time.sleep(backoff + random.uniform(0, backoff * 0.25))
763
+ raise RuntimeError("Unexpected retry loop exit") from last_exc
742
764
 
743
765
  async def _do_request_async(self, payload: Dict[str, Any]) -> Dict[str, Any]:
744
766
  """Perform an asynchronous (non-streaming) HTTP POST with retries."""
@@ -784,24 +806,48 @@ class ChatGithubCopilot(BaseChatModel):
784
806
  ) -> AsyncIterator[Dict[str, Any]]:
785
807
  """Perform an asynchronous streaming HTTP POST and yield parsed SSE chunks."""
786
808
  headers = self._build_headers()
787
- async with httpx.AsyncClient(timeout=self.timeout) as client:
788
- async with client.stream(
789
- "POST",
790
- self._inference_url,
791
- headers=headers,
792
- json=payload,
793
- ) as response:
794
- response.raise_for_status()
795
- async for line in response.aiter_lines():
796
- line = line.strip()
797
- if not line or line == "data: [DONE]":
798
- continue
799
- if line.startswith("data: "):
800
- line = line[len("data: ") :]
801
- try:
802
- yield json.loads(line)
803
- except json.JSONDecodeError:
804
- continue
809
+ last_exc: Optional[Exception] = None
810
+ for attempt in range(self.max_retries + 1):
811
+ try:
812
+ async with httpx.AsyncClient(timeout=self.timeout) as client:
813
+ async with client.stream(
814
+ "POST",
815
+ self._inference_url,
816
+ headers=headers,
817
+ json=payload,
818
+ ) as response:
819
+ if response.status_code == 401:
820
+ await self._refresh_token_async()
821
+ headers = self._build_headers()
822
+ raise httpx.TransportError(
823
+ "401 — token refreshed, retrying"
824
+ )
825
+ response.raise_for_status()
826
+ async for line in response.aiter_lines():
827
+ line = line.strip()
828
+ if not line or line == "data: [DONE]":
829
+ continue
830
+ if line.startswith("data: "):
831
+ line = line[len("data: ") :]
832
+ try:
833
+ yield json.loads(line)
834
+ except json.JSONDecodeError:
835
+ continue
836
+ return
837
+ except (httpx.TimeoutException, httpx.TransportError) as exc:
838
+ last_exc = exc
839
+ if attempt == self.max_retries:
840
+ raise
841
+ except httpx.HTTPStatusError as exc:
842
+ if exc.response.status_code < 500:
843
+ raise
844
+ last_exc = exc
845
+ if attempt == self.max_retries:
846
+ raise
847
+ if attempt < self.max_retries:
848
+ backoff = 2**attempt
849
+ await asyncio.sleep(backoff + random.uniform(0, backoff * 0.25))
850
+ raise RuntimeError("Unexpected retry loop exit") from last_exc
805
851
 
806
852
  # ------------------------------------------------------------------
807
853
  # Stream delta → AIMessageChunk helpers
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "langchain-githubcopilot-chat"
7
- version = "0.5.0"
7
+ version = "0.5.1"
8
8
  description = "An integration package connecting GithubcopilotChat and LangChain"
9
9
  authors = ["YIhan Wu <iumm@ibat.ac.cn>"]
10
10
  readme = "README.md"