jaf-py 2.5.8__py3-none-any.whl → 2.5.9__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.
- jaf/__init__.py +1 -1
- jaf/core/tracing.py +1 -1
- jaf/providers/model.py +61 -93
- {jaf_py-2.5.8.dist-info → jaf_py-2.5.9.dist-info}/METADATA +2 -2
- {jaf_py-2.5.8.dist-info → jaf_py-2.5.9.dist-info}/RECORD +9 -9
- {jaf_py-2.5.8.dist-info → jaf_py-2.5.9.dist-info}/WHEEL +0 -0
- {jaf_py-2.5.8.dist-info → jaf_py-2.5.9.dist-info}/entry_points.txt +0 -0
- {jaf_py-2.5.8.dist-info → jaf_py-2.5.9.dist-info}/licenses/LICENSE +0 -0
- {jaf_py-2.5.8.dist-info → jaf_py-2.5.9.dist-info}/top_level.txt +0 -0
jaf/__init__.py
CHANGED
|
@@ -191,7 +191,7 @@ def generate_run_id() -> RunId:
|
|
|
191
191
|
"""Generate a new run ID."""
|
|
192
192
|
return create_run_id(str(uuid.uuid4()))
|
|
193
193
|
|
|
194
|
-
__version__ = "2.5.
|
|
194
|
+
__version__ = "2.5.9"
|
|
195
195
|
__all__ = [
|
|
196
196
|
# Core types and functions
|
|
197
197
|
"TraceId", "RunId", "ValidationResult", "Message", "ModelConfig",
|
jaf/core/tracing.py
CHANGED
jaf/providers/model.py
CHANGED
|
@@ -6,13 +6,12 @@ starting with LiteLLM for multi-provider support.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
from typing import Any, Dict, Optional, TypeVar, AsyncIterator
|
|
9
|
-
import asyncio
|
|
10
9
|
import httpx
|
|
11
10
|
import time
|
|
12
11
|
import os
|
|
13
12
|
import base64
|
|
14
13
|
|
|
15
|
-
from openai import
|
|
14
|
+
from openai import AsyncOpenAI
|
|
16
15
|
from pydantic import BaseModel
|
|
17
16
|
import litellm
|
|
18
17
|
|
|
@@ -150,7 +149,7 @@ def make_litellm_provider(
|
|
|
150
149
|
print(f"Warning: Could not configure proxy: {e}")
|
|
151
150
|
# Fall back to environment variables for proxy
|
|
152
151
|
|
|
153
|
-
self.client =
|
|
152
|
+
self.client = AsyncOpenAI(**client_kwargs)
|
|
154
153
|
self.default_timeout = default_timeout
|
|
155
154
|
|
|
156
155
|
async def get_completion(
|
|
@@ -238,7 +237,7 @@ def make_litellm_provider(
|
|
|
238
237
|
request_params["response_format"] = {"type": "json_object"}
|
|
239
238
|
|
|
240
239
|
# Make the API call
|
|
241
|
-
response = self.client.chat.completions.create(**request_params)
|
|
240
|
+
response = await self.client.chat.completions.create(**request_params)
|
|
242
241
|
|
|
243
242
|
# Return in the expected format that the engine expects
|
|
244
243
|
choice = response.choices[0]
|
|
@@ -351,99 +350,68 @@ def make_litellm_provider(
|
|
|
351
350
|
# Enable streaming
|
|
352
351
|
request_params["stream"] = True
|
|
353
352
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
SENTINEL = object()
|
|
353
|
+
# Use async streaming directly with AsyncOpenAI
|
|
354
|
+
stream = await self.client.chat.completions.create(**request_params)
|
|
357
355
|
|
|
358
|
-
|
|
356
|
+
async for chunk in stream:
|
|
359
357
|
try:
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
358
|
+
# Best-effort extraction of raw for debugging
|
|
359
|
+
try:
|
|
360
|
+
raw_obj = chunk.model_dump() # pydantic BaseModel
|
|
361
|
+
except Exception:
|
|
362
|
+
raw_obj = None
|
|
364
363
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
)
|
|
414
|
-
),
|
|
415
|
-
raw=raw_obj
|
|
416
|
-
))
|
|
417
|
-
except Exception:
|
|
418
|
-
# Skip malformed tool-call deltas
|
|
419
|
-
continue
|
|
420
|
-
|
|
421
|
-
# Completion ended
|
|
422
|
-
if finish_reason:
|
|
423
|
-
_put(CompletionStreamChunk(is_done=True, finish_reason=finish_reason, raw=raw_obj))
|
|
424
|
-
except Exception:
|
|
425
|
-
# Skip individual chunk errors, keep streaming
|
|
426
|
-
continue
|
|
364
|
+
choice = None
|
|
365
|
+
if getattr(chunk, "choices", None):
|
|
366
|
+
choice = chunk.choices[0]
|
|
367
|
+
|
|
368
|
+
if choice is None:
|
|
369
|
+
continue
|
|
370
|
+
|
|
371
|
+
delta = getattr(choice, "delta", None)
|
|
372
|
+
finish_reason = getattr(choice, "finish_reason", None)
|
|
373
|
+
|
|
374
|
+
# Text content delta
|
|
375
|
+
if delta is not None:
|
|
376
|
+
content_delta = getattr(delta, "content", None)
|
|
377
|
+
if content_delta:
|
|
378
|
+
yield CompletionStreamChunk(delta=content_delta, raw=raw_obj)
|
|
379
|
+
|
|
380
|
+
# Tool call deltas
|
|
381
|
+
tool_calls = getattr(delta, "tool_calls", None)
|
|
382
|
+
if isinstance(tool_calls, list):
|
|
383
|
+
for tc in tool_calls:
|
|
384
|
+
# Each tc is likely a pydantic model with .index/.id/.function
|
|
385
|
+
try:
|
|
386
|
+
idx = getattr(tc, "index", 0) or 0
|
|
387
|
+
tc_id = getattr(tc, "id", None)
|
|
388
|
+
fn = getattr(tc, "function", None)
|
|
389
|
+
fn_name = getattr(fn, "name", None) if fn is not None else None
|
|
390
|
+
# OpenAI streams "arguments" as incremental deltas
|
|
391
|
+
args_delta = getattr(fn, "arguments", None) if fn is not None else None
|
|
392
|
+
|
|
393
|
+
yield CompletionStreamChunk(
|
|
394
|
+
tool_call_delta=ToolCallDelta(
|
|
395
|
+
index=idx,
|
|
396
|
+
id=tc_id,
|
|
397
|
+
type='function',
|
|
398
|
+
function=ToolCallFunctionDelta(
|
|
399
|
+
name=fn_name,
|
|
400
|
+
arguments_delta=args_delta
|
|
401
|
+
)
|
|
402
|
+
),
|
|
403
|
+
raw=raw_obj
|
|
404
|
+
)
|
|
405
|
+
except Exception:
|
|
406
|
+
# Skip malformed tool-call deltas
|
|
407
|
+
continue
|
|
408
|
+
|
|
409
|
+
# Completion ended
|
|
410
|
+
if finish_reason:
|
|
411
|
+
yield CompletionStreamChunk(is_done=True, finish_reason=finish_reason, raw=raw_obj)
|
|
427
412
|
except Exception:
|
|
428
|
-
#
|
|
429
|
-
|
|
430
|
-
finally:
|
|
431
|
-
try:
|
|
432
|
-
asyncio.run_coroutine_threadsafe(queue.put(SENTINEL), loop)
|
|
433
|
-
except RuntimeError:
|
|
434
|
-
pass
|
|
435
|
-
|
|
436
|
-
# Start producer in background
|
|
437
|
-
loop.run_in_executor(None, _producer)
|
|
438
|
-
|
|
439
|
-
# Consume queue and yield
|
|
440
|
-
while True:
|
|
441
|
-
item = await queue.get()
|
|
442
|
-
if item is SENTINEL:
|
|
443
|
-
break
|
|
444
|
-
# Guarantee type for consumers
|
|
445
|
-
if isinstance(item, CompletionStreamChunk):
|
|
446
|
-
yield item
|
|
413
|
+
# Skip individual chunk errors, keep streaming
|
|
414
|
+
continue
|
|
447
415
|
|
|
448
416
|
return LiteLLMProvider()
|
|
449
417
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jaf-py
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.9
|
|
4
4
|
Summary: A purely functional agent framework with immutable state and composable tools - Python implementation
|
|
5
5
|
Author: JAF Contributors
|
|
6
6
|
Maintainer: JAF Contributors
|
|
@@ -82,7 +82,7 @@ Dynamic: license-file
|
|
|
82
82
|
|
|
83
83
|
<!--  -->
|
|
84
84
|
|
|
85
|
-
[](https://github.com/xynehq/jaf-py)
|
|
86
86
|
[](https://www.python.org/)
|
|
87
87
|
[](https://xynehq.github.io/jaf-py/)
|
|
88
88
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
jaf/__init__.py,sha256=
|
|
1
|
+
jaf/__init__.py,sha256=4x42grDiLvjqwi6Tu6YLSlyKI31NXQZnLioCfqL-K6Q,8260
|
|
2
2
|
jaf/cli.py,sha256=Af4di_NZ7rZ4wFl0R4EZh611NgJ--TL03vNyZ2M1_FY,8477
|
|
3
3
|
jaf/exceptions.py,sha256=nl8JY355u7oTXB3PmC_LhnUaL8fzk2K4EaWM4fVpMPE,9196
|
|
4
4
|
jaf/a2a/__init__.py,sha256=p4YVthZH0ow1ZECqWTQ0aQl8JWySYZb25jlzZJ09na4,7662
|
|
@@ -55,7 +55,7 @@ jaf/core/state.py,sha256=oNCVXPWLkqnBQObdQX10TcmZ0eOF3wKG6DtL3kF6ohw,9649
|
|
|
55
55
|
jaf/core/streaming.py,sha256=wDjbxGdLehPs2ImzKAftEvb7ruOBldSvYYnrSeD2xJg,17084
|
|
56
56
|
jaf/core/tool_results.py,sha256=-bTOqOX02lMyslp5Z4Dmuhx0cLd5o7kgR88qK2HO_sw,11323
|
|
57
57
|
jaf/core/tools.py,sha256=84N9A7QQ3xxcOs2eUUot3nmCnt5i7iZT9VwkuzuFBxQ,16274
|
|
58
|
-
jaf/core/tracing.py,sha256=
|
|
58
|
+
jaf/core/tracing.py,sha256=ZhQB8GfxS1SaiYay0RMEzgNzRV0vr7tZ9gV8Mh5M9b4,53367
|
|
59
59
|
jaf/core/types.py,sha256=RLfFS5TpJiog5-mAVMH_7oM7ZEJqGsZBbrOQiUpGUM4,33042
|
|
60
60
|
jaf/core/workflows.py,sha256=Ul-82gzjIXtkhnSMSPv-8igikjkMtW1EBo9yrfodtvI,26294
|
|
61
61
|
jaf/memory/__init__.py,sha256=-L98xlvihurGAzF0DnXtkueDVvO_wV2XxxEwAWdAj50,1400
|
|
@@ -74,7 +74,7 @@ jaf/policies/handoff.py,sha256=KJYYuL9T6v6DECRhnsS2Je6q4Aj9_zC5d_KBnvEnZNE,8318
|
|
|
74
74
|
jaf/policies/validation.py,sha256=wn-7ynH10E5nk-_r1_kHIYHrBGmLX0EFr-FUTHrsxvc,10903
|
|
75
75
|
jaf/providers/__init__.py,sha256=lIbl1JvGrDhI9CzEk79N8yJNhf7ww_aWD-F40MnG3vY,2174
|
|
76
76
|
jaf/providers/mcp.py,sha256=WxcC8gUFpDBBYyhorMcc1jHq3xMDMBtnwyRPthfL0S0,13074
|
|
77
|
-
jaf/providers/model.py,sha256=
|
|
77
|
+
jaf/providers/model.py,sha256=Hk9NfkThw1MYntKcrPVvHkCyyrOLDvScIjVq0mk_fhs,37838
|
|
78
78
|
jaf/server/__init__.py,sha256=fMPnLZBRm6t3yQrr7-PnoHAQ8qj9o6Z1AJLM1M6bIS0,392
|
|
79
79
|
jaf/server/main.py,sha256=CTb0ywbPIq9ELfay5MKChVR7BpIQOoEbPjPfpzo2aBQ,2152
|
|
80
80
|
jaf/server/server.py,sha256=cbdhVTPoWa7rVIX3DDLoXjppeGTKQWNFj3NA1jrZN88,46830
|
|
@@ -88,9 +88,9 @@ jaf/visualization/functional_core.py,sha256=zedMDZbvjuOugWwnh6SJ2stvRNQX1Hlkb9Ab
|
|
|
88
88
|
jaf/visualization/graphviz.py,sha256=WTOM6UP72-lVKwI4_SAr5-GCC3ouckxHv88ypCDQWJ0,12056
|
|
89
89
|
jaf/visualization/imperative_shell.py,sha256=GpMrAlMnLo2IQgyB2nardCz09vMvAzaYI46MyrvJ0i4,2593
|
|
90
90
|
jaf/visualization/types.py,sha256=QQcbVeQJLuAOXk8ynd08DXIS-PVCnv3R-XVE9iAcglw,1389
|
|
91
|
-
jaf_py-2.5.
|
|
92
|
-
jaf_py-2.5.
|
|
93
|
-
jaf_py-2.5.
|
|
94
|
-
jaf_py-2.5.
|
|
95
|
-
jaf_py-2.5.
|
|
96
|
-
jaf_py-2.5.
|
|
91
|
+
jaf_py-2.5.9.dist-info/licenses/LICENSE,sha256=LXUQBJxdyr-7C4bk9cQBwvsF_xwA-UVstDTKabpcjlI,1063
|
|
92
|
+
jaf_py-2.5.9.dist-info/METADATA,sha256=8JMKpeIJvJ2pNrEzKOGoNdI8WFce8MNuSKioCvvrpak,27743
|
|
93
|
+
jaf_py-2.5.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
94
|
+
jaf_py-2.5.9.dist-info/entry_points.txt,sha256=OtIJeNJpb24kgGrqRx9szGgDx1vL9ayq8uHErmu7U5w,41
|
|
95
|
+
jaf_py-2.5.9.dist-info/top_level.txt,sha256=Xu1RZbGaM4_yQX7bpalo881hg7N_dybaOW282F15ruE,4
|
|
96
|
+
jaf_py-2.5.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|