projectdavid 1.33.10__py3-none-any.whl → 1.33.11__py3-none-any.whl

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.

Potentially problematic release.


This version of projectdavid might be problematic. Click here for more details.

@@ -14,9 +14,7 @@ class SynchronousInferenceStream:
14
14
  _GLOBAL_LOOP = asyncio.new_event_loop()
15
15
  asyncio.set_event_loop(_GLOBAL_LOOP)
16
16
 
17
- # --------------------------------------------------------------
18
- # ctor / setup
19
- # --------------------------------------------------------------
17
+ # ────────────────────────────────────────────────────────────
20
18
  def __init__(self, inference) -> None:
21
19
  self.inference_client = inference
22
20
  self.user_id: Optional[str] = None
@@ -26,6 +24,7 @@ class SynchronousInferenceStream:
26
24
  self.run_id: Optional[str] = None
27
25
  self.api_key: Optional[str] = None
28
26
 
27
+ # ────────────────────────────────────────────────────────────
29
28
  def setup(
30
29
  self,
31
30
  user_id: str,
@@ -42,9 +41,7 @@ class SynchronousInferenceStream:
42
41
  self.run_id = run_id
43
42
  self.api_key = api_key
44
43
 
45
- # --------------------------------------------------------------
46
- # main streaming entry-point
47
- # --------------------------------------------------------------
44
+ # ────────────────────────────────────────────────────────────
48
45
  def stream_chunks(
49
46
  self,
50
47
  provider: str,
@@ -71,61 +68,86 @@ class SynchronousInferenceStream:
71
68
 
72
69
  agen = _stream_chunks_async().__aiter__()
73
70
 
74
- # ---------- suppression chain ----------
71
+ # ── build the <fc> suppressor chain ─────────────────────────
75
72
  if suppress_fc:
76
73
  _suppressor = FunctionCallSuppressor()
77
74
  _peek_gate = PeekGate(_suppressor)
78
75
 
79
- def _filter_text(txt: str) -> str:
76
+ def _filter_text(txt: str) -> str: # noqa: D401
80
77
  return _peek_gate.feed(txt)
81
78
 
82
79
  else:
83
80
 
84
- def _filter_text(txt: str) -> str: # no-op
81
+ def _filter_text(txt: str) -> str: # noqa: D401
85
82
  return txt
86
83
 
87
- # ---------------------------------------
88
-
84
+ # helper – drain **all** residual bytes from the chain
85
+ def _drain_filters() -> Optional[dict]:
86
+ if not suppress_fc:
87
+ return None
88
+ parts: list[str] = []
89
+ while True:
90
+ out = _filter_text("") # empty feed ⇒ “give me whatever’s left”
91
+ if not out:
92
+ break
93
+ parts.append(out)
94
+ if parts:
95
+ return {"type": "content", "content": "".join(parts)}
96
+ return None
97
+
98
+ # ── main loop ─────────────────────────────────────────────
89
99
  while True:
90
100
  try:
91
101
  chunk = self._GLOBAL_LOOP.run_until_complete(
92
102
  asyncio.wait_for(agen.__anext__(), timeout=timeout_per_chunk)
93
103
  )
94
104
 
95
- # provider-labelled function_call
105
+ # ① drop provider-labelled function_call objects
96
106
  if suppress_fc and chunk.get("type") == "function_call":
97
- LOG.debug("[SUPPRESSOR] blocked provider-labelled function_call")
107
+ LOG.debug("[SUPPRESS] provider function_call dropped")
108
+ continue
109
+
110
+ # ② hot-code & file-preview payloads always pass
111
+ if chunk.get("type") in ("hot_code", "hot_code_output"):
112
+ yield chunk
113
+ continue
114
+
115
+ if (
116
+ chunk.get("stream_type") == "code_execution"
117
+ and chunk.get("chunk", {}).get("type") == "code_interpreter_stream"
118
+ ):
119
+ yield chunk
98
120
  continue
99
121
 
100
- # inline content
122
+ # ordinary TEXT content — run through the <fc> filter
101
123
  if isinstance(chunk.get("content"), str):
102
124
  chunk["content"] = _filter_text(chunk["content"])
103
125
  if chunk["content"] == "":
104
- continue # fully suppressed (or still peeking)
105
-
106
- # additional raw inline suppression for partial JSON
107
- if (
108
- '"name": "code_interpreter"' in chunk["content"]
109
- and '"arguments": {"code"' in chunk["content"]
110
- ):
111
- LOG.debug("[SUPPRESSOR] inline code_interpreter match blocked")
112
- continue
126
+ continue # fully suppressed / still buffering
113
127
 
128
+ # ④ everything else streams unchanged
114
129
  yield chunk
115
130
 
131
+ # ─────────── graceful endings ───────────
116
132
  except StopAsyncIteration:
133
+ if tail := _drain_filters():
134
+ yield tail
117
135
  LOG.info("Stream completed normally.")
118
136
  break
137
+
119
138
  except asyncio.TimeoutError:
120
- LOG.error("[TimeoutError] Timeout occurred, stopping stream.")
139
+ if tail := _drain_filters():
140
+ yield tail
141
+ LOG.error("[TimeoutError] Chunk wait expired – aborting stream.")
121
142
  break
122
- except Exception as e:
123
- LOG.error("Unexpected error during streaming completions: %s", e)
143
+
144
+ except Exception as exc: # noqa: BLE001
145
+ if tail := _drain_filters():
146
+ yield tail
147
+ LOG.error("Unexpected streaming error: %s", exc, exc_info=True)
124
148
  break
125
149
 
126
- # --------------------------------------------------------------
127
- # housekeeping
128
- # --------------------------------------------------------------
150
+ # ────────────────────────────────────────────────────────────
129
151
  @classmethod
130
152
  def shutdown_loop(cls) -> None:
131
153
  if cls._GLOBAL_LOOP and not cls._GLOBAL_LOOP.is_closed():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: projectdavid
3
- Version: 1.33.10
3
+ Version: 1.33.11
4
4
  Summary: Python SDK for interacting with the Entities Assistant API.
5
5
  Author-email: Francis Neequaye Armah <francis.neequaye@projectdavid.co.uk>
6
6
  License: PolyForm Noncommercial License 1.0.0
@@ -16,7 +16,7 @@ projectdavid/clients/files_client.py,sha256=XkIDzbQFGDrd88taf0Kouc_4YJOPIYEHiIyW
16
16
  projectdavid/clients/inference_client.py,sha256=xz4ACPv5Tkis604QxO5mJX1inH_TGDfQP-31geETYpE,6609
17
17
  projectdavid/clients/messages_client.py,sha256=467xeIt3VYs6cG8-bl-eDRi_auWOPmfd5tSJDmQSJUI,17232
18
18
  projectdavid/clients/runs.py,sha256=-fXOq5L9w2efDPmZkNxb0s2yjl6oN0XN4_aLXqaeceo,25270
19
- projectdavid/clients/synchronous_inference_wrapper.py,sha256=Rv7TGZBnzMOBDw3BwguDOHcVmwLvcjHp7j6V8OAqpwM,4686
19
+ projectdavid/clients/synchronous_inference_wrapper.py,sha256=smbKBkwJZHX2LCqb0pO9RS7N7GFmruzCfmxrQsmJv_o,6204
20
20
  projectdavid/clients/threads_client.py,sha256=ekzU5w14zftmtmFkiec3NC90Of-_KVSUY1qH9cmfSFg,6771
21
21
  projectdavid/clients/tools_client.py,sha256=GkCVOmwpAoPqVt6aYmH0G1HIFha3iEwR9IIf9teR0j8,11487
22
22
  projectdavid/clients/users_client.py,sha256=eCuUb9qvyH1GUFhZu6TRL9zdoK-qzHSs8-Vmrk_0mmg,13729
@@ -35,8 +35,8 @@ projectdavid/utils/monitor_launcher.py,sha256=3YAgJdeuaUvq3JGvpA4ymqFsAnk29nH5q9
35
35
  projectdavid/utils/peek_gate.py,sha256=5whMRnDOQjATRpThWDJkvY9ScXuJ7Sd_-9rvGgXeTAQ,2532
36
36
  projectdavid/utils/run_monitor.py,sha256=F_WkqIP-qnWH-4llIbileWWLfRj2Q1Cg-ni23SR1rec,3786
37
37
  projectdavid/utils/vector_search_formatter.py,sha256=YTe3HPGec26qGY7uxY8_GS8lc4QaN6aNXMzkl29nZpI,1735
38
- projectdavid-1.33.10.dist-info/licenses/LICENSE,sha256=_8yjiEGttpS284BkfhXxfERqTRZW_tUaHiBB0GTJTMg,4563
39
- projectdavid-1.33.10.dist-info/METADATA,sha256=fLLv7ywPdpBY5QMaooyy9CEFhx2cnVIY_Z8E-rvfgvk,11555
40
- projectdavid-1.33.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
41
- projectdavid-1.33.10.dist-info/top_level.txt,sha256=kil8GU4s7qYRfNnzGnFHhZnSNRSxgNG-J4HLgQMmMtw,13
42
- projectdavid-1.33.10.dist-info/RECORD,,
38
+ projectdavid-1.33.11.dist-info/licenses/LICENSE,sha256=_8yjiEGttpS284BkfhXxfERqTRZW_tUaHiBB0GTJTMg,4563
39
+ projectdavid-1.33.11.dist-info/METADATA,sha256=aqETkoAw4NxCKZg56GnWf4QNVMdl4-mCZb0f78ej4EQ,11555
40
+ projectdavid-1.33.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
41
+ projectdavid-1.33.11.dist-info/top_level.txt,sha256=kil8GU4s7qYRfNnzGnFHhZnSNRSxgNG-J4HLgQMmMtw,13
42
+ projectdavid-1.33.11.dist-info/RECORD,,