libentry 1.28__py3-none-any.whl → 1.28.2__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.
libentry/mcp/client.py CHANGED
@@ -143,17 +143,23 @@ class SubroutineMixIn(abc.ABC):
143
143
  return self._iter_results_from_subroutine(response)
144
144
 
145
145
  @staticmethod
146
- def _iter_results_from_subroutine(responses: Iterable[SubroutineResponse]) -> Iterable[JSONType]:
147
- full_result = None
148
- for response in responses:
149
- if response.error is None:
150
- if response.chunk:
151
- yield response.result
146
+ def _iter_results_from_subroutine(response: Iterable[SubroutineResponse]) -> Iterable[JSONType]:
147
+ it = iter(response)
148
+ try:
149
+ while True:
150
+ chunk = next(it)
151
+ if chunk.error is None:
152
+ yield chunk.result
152
153
  else:
153
- full_result = response.result
154
+ raise ServiceError.from_subroutine_error(chunk.error)
155
+ except StopIteration as e:
156
+ chunk = e.value
157
+ if chunk is None:
158
+ return None
159
+ elif chunk.error is None:
160
+ return chunk.result
154
161
  else:
155
- raise ServiceError.from_subroutine_error(response.error)
156
- return full_result
162
+ raise ServiceError.from_subroutine_error(chunk.error)
157
163
 
158
164
  def get(
159
165
  self,
@@ -223,12 +229,24 @@ class JSONRPCMixIn(abc.ABC):
223
229
  return self._iter_results_from_jsonrpc(response)
224
230
 
225
231
  @staticmethod
226
- def _iter_results_from_jsonrpc(responses: Iterable[JSONRPCResponse]) -> Iterable[JSONType]:
227
- for response in responses:
228
- if response.error is None:
229
- yield response.result
232
+ def _iter_results_from_jsonrpc(response: Iterable[JSONRPCResponse]) -> Iterable[JSONType]:
233
+ it = iter(response)
234
+ try:
235
+ while True:
236
+ chunk = next(it)
237
+ if chunk.error is None:
238
+ yield chunk.result
239
+ else:
240
+ raise ServiceError.from_jsonrpc_error(chunk.error)
241
+ except StopIteration as e:
242
+ chunk = e.value
243
+ if chunk is None:
244
+ return None
245
+ elif chunk.error is None:
246
+ return chunk.result
230
247
  else:
231
- raise ServiceError.from_jsonrpc_error(response.error)
248
+ raise ServiceError.from_jsonrpc_error(chunk.error)
249
+
232
250
 
233
251
 
234
252
  class MCPMixIn(JSONRPCMixIn, abc.ABC):
@@ -492,14 +510,16 @@ class APIClient(SubroutineMixIn, MCPMixIn):
492
510
 
493
511
  @staticmethod
494
512
  def _iter_subroutine_responses(response: HTTPResponse) -> Iterable[SubroutineResponse]:
513
+ return_response = None
495
514
  for sse in response.content:
496
515
  assert isinstance(sse, SSE)
497
- if sse.event != "message":
498
- continue
499
- if not sse.data:
500
- continue
501
- json_obj = json.loads(sse.data)
502
- yield SubroutineResponse.model_validate(json_obj)
516
+ if sse.event == "message" and sse.data:
517
+ json_obj = json.loads(sse.data)
518
+ yield SubroutineResponse.model_validate(json_obj)
519
+ elif sse.event == "return" and sse.data:
520
+ json_obj = json.loads(sse.data)
521
+ return_response = SubroutineResponse.model_validate(json_obj)
522
+ return return_response
503
523
 
504
524
  def jsonrpc_request(
505
525
  self,
@@ -520,14 +540,16 @@ class APIClient(SubroutineMixIn, MCPMixIn):
520
540
 
521
541
  @staticmethod
522
542
  def _iter_jsonrpc_responses(response: HTTPResponse) -> Iterable[JSONRPCResponse]:
543
+ return_response = None
523
544
  for sse in response.content:
524
545
  assert isinstance(sse, SSE)
525
- if sse.event != "message":
526
- continue
527
- if not sse.data:
528
- continue
529
- json_obj = json.loads(sse.data)
530
- yield JSONRPCResponse.model_validate(json_obj)
546
+ if sse.event == "message" and sse.data:
547
+ json_obj = json.loads(sse.data)
548
+ yield JSONRPCResponse.model_validate(json_obj)
549
+ elif sse.event == "return" and sse.data:
550
+ json_obj = json.loads(sse.data)
551
+ return_response = JSONRPCResponse.model_validate(json_obj)
552
+ return return_response
531
553
 
532
554
  def jsonrpc_notify(
533
555
  self,
libentry/mcp/service.py CHANGED
@@ -100,24 +100,19 @@ class SubroutineAdapter:
100
100
  results: Iterable[Any]
101
101
  ) -> Iterable[SubroutineResponse]:
102
102
  it = iter(results)
103
- while True:
104
- try:
103
+ try:
104
+ while True:
105
105
  result = next(it)
106
106
  if not isinstance(result, SubroutineResponse):
107
107
  result = SubroutineResponse(result=result)
108
- result.chunk = True
109
108
  yield result
110
- except StopIteration as e:
111
- final_result = e.value
112
- if not isinstance(final_result, SubroutineResponse):
113
- final_result = SubroutineResponse(result=final_result)
114
- final_result.chunk = False
115
- yield final_result
116
- break
117
- except Exception as e:
118
- final_result = SubroutineResponse(error=SubroutineError.from_exception(e))
119
- yield final_result
120
- break
109
+ except StopIteration as e:
110
+ result = e.value
111
+ if not isinstance(result, SubroutineResponse):
112
+ result = SubroutineResponse(result=result)
113
+ return result
114
+ except Exception as e:
115
+ yield SubroutineResponse(error=SubroutineError.from_exception(e))
121
116
 
122
117
 
123
118
  class JSONRPCAdapter:
@@ -341,15 +336,36 @@ class FlaskHandler:
341
336
  )
342
337
 
343
338
  def _iter_sse_stream(self, events: Iterable[Union[SSE, Dict[str, Any]]]) -> Iterable[str]:
344
- for item in events:
345
- if isinstance(item, SSE):
346
- event = item.event
347
- data = item.data
348
- else:
349
- event = "message"
350
- data = item
339
+ it = iter(events)
340
+ try:
341
+ while True:
342
+ item = next(it)
343
+ if isinstance(item, SSE):
344
+ event = item.event
345
+ data = item.data
346
+ else:
347
+ event = "message"
348
+ data = item
349
+ yield "event:"
350
+ yield event
351
+ if data is not None:
352
+ yield "\n"
353
+ yield "data:"
354
+ if isinstance(data, BaseModel):
355
+ # BaseModel
356
+ yield json.dumps(data.model_dump(exclude_none=True))
357
+ elif isinstance(data, (Dict, List)):
358
+ # JSON Object and Array
359
+ yield json.dumps(data)
360
+ else:
361
+ # Plain text
362
+ yield str(data)
363
+ yield "\n\n"
364
+ except StopIteration as e:
365
+ item = e.value
366
+ data = item.data if isinstance(item, SSE) else item
351
367
  yield "event:"
352
- yield event
368
+ yield "return"
353
369
  if data is not None:
354
370
  yield "\n"
355
371
  yield "data:"
libentry/mcp/types.py CHANGED
@@ -48,7 +48,6 @@ class SubroutineError(BaseModel):
48
48
  class SubroutineResponse(BaseModel):
49
49
  result: Optional[Any] = None
50
50
  error: Optional[SubroutineError] = None
51
- chunk: bool = False
52
51
 
53
52
 
54
53
  class HTTPOptions(BaseModel):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: libentry
3
- Version: 1.28
3
+ Version: 1.28.2
4
4
  Summary: Entries for experimental utilities.
5
5
  Home-page: https://github.com/XoriieInpottn/libentry
6
6
  Author: xi
@@ -12,9 +12,9 @@ libentry/test_api.py,sha256=bs7P8gveLtuUvHxrpujSrfuYqLVJ3fOXVg_MZnZxoJ4,4504
12
12
  libentry/utils.py,sha256=vCm6UyAlibnPOlPJHZO57u3TXhw5PZmGM5_vBAPUnB4,1981
13
13
  libentry/mcp/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
14
14
  libentry/mcp/api.py,sha256=GDErVCz_hh_ZeMxLS8bTPyBUhCTHw3Mm-nGFMV2W2yo,3669
15
- libentry/mcp/client.py,sha256=OzAgM-hZ5t24A7MC-i_FkchxQaYM17T6E6M0jPuZJwk,23243
16
- libentry/mcp/service.py,sha256=cE6K6RVDQ9Jc4pxcJUWOr5zWJMpSvROL54cq8vbJWHE,39130
17
- libentry/mcp/types.py,sha256=P4lnwDCdETTzfoD7u1XMqx9ZKN4mXl0KSEMk4e_o_k0,12413
15
+ libentry/mcp/client.py,sha256=u9u-hVwcHQLc9o-_CJumz2vtIDf-ZgQcgDTD5xSmZPA,24143
16
+ libentry/mcp/service.py,sha256=RQ658-Ci69Z_h5d4Y43NN1BeykC8mjRpYbOPOGFxzlc,39736
17
+ libentry/mcp/types.py,sha256=aAoVO4jjqEvDzNneuZapmRYonLLnGsbcLoypVyRNNYg,12389
18
18
  libentry/service/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
19
19
  libentry/service/common.py,sha256=OVaW2afgKA6YqstJmtnprBCqQEUZEWotZ6tHavmJJeU,42
20
20
  libentry/service/flask.py,sha256=2egCFFhRAfLpmSyibgaJ-3oexI-j27P1bmaPEn-hSlc,13817
@@ -22,10 +22,10 @@ libentry/service/list.py,sha256=ElHWhTgShGOhaxMUEwVbMXos0NQKjHsODboiQ-3AMwE,1397
22
22
  libentry/service/running.py,sha256=FrPJoJX6wYxcHIysoatAxhW3LajCCm0Gx6l7__6sULQ,5105
23
23
  libentry/service/start.py,sha256=mZT7b9rVULvzy9GTZwxWnciCHgv9dbGN2JbxM60OMn4,1270
24
24
  libentry/service/stop.py,sha256=wOpwZgrEJ7QirntfvibGq-XsTC6b3ELhzRW2zezh-0s,1187
25
- libentry-1.28.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
26
- libentry-1.28.dist-info/METADATA,sha256=NmtlVZk1U8IW_q8pw22_e6UF3UvAhgIhFLyzF3i1BRU,1133
27
- libentry-1.28.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
28
- libentry-1.28.dist-info/entry_points.txt,sha256=1v_nLVDsjvVJp9SWhl4ef2zZrsLTBtFWgrYFgqvQBgc,61
29
- libentry-1.28.dist-info/top_level.txt,sha256=u2uF6-X5fn2Erf9PYXOg_6tntPqTpyT-yzUZrltEd6I,9
30
- libentry-1.28.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
31
- libentry-1.28.dist-info/RECORD,,
25
+ libentry-1.28.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
26
+ libentry-1.28.2.dist-info/METADATA,sha256=uM20K0CHXqJCStF-O5_s5lLE_7rptJDY0gdt4NvATCA,1135
27
+ libentry-1.28.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
28
+ libentry-1.28.2.dist-info/entry_points.txt,sha256=1v_nLVDsjvVJp9SWhl4ef2zZrsLTBtFWgrYFgqvQBgc,61
29
+ libentry-1.28.2.dist-info/top_level.txt,sha256=u2uF6-X5fn2Erf9PYXOg_6tntPqTpyT-yzUZrltEd6I,9
30
+ libentry-1.28.2.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
31
+ libentry-1.28.2.dist-info/RECORD,,