jaf-py 2.5.3__py3-none-any.whl → 2.5.5__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/engine.py +159 -117
- jaf/core/regeneration.py +392 -0
- jaf/core/tracing.py +1 -1
- jaf/core/types.py +115 -2
- jaf/memory/providers/in_memory.py +174 -1
- jaf/memory/providers/postgres.py +211 -1
- jaf/memory/providers/redis.py +189 -1
- jaf/memory/types.py +35 -1
- jaf/memory/utils.py +2 -0
- jaf/server/server.py +163 -0
- jaf/server/types.py +49 -1
- {jaf_py-2.5.3.dist-info → jaf_py-2.5.5.dist-info}/METADATA +2 -2
- {jaf_py-2.5.3.dist-info → jaf_py-2.5.5.dist-info}/RECORD +18 -17
- {jaf_py-2.5.3.dist-info → jaf_py-2.5.5.dist-info}/WHEEL +0 -0
- {jaf_py-2.5.3.dist-info → jaf_py-2.5.5.dist-info}/entry_points.txt +0 -0
- {jaf_py-2.5.3.dist-info → jaf_py-2.5.5.dist-info}/licenses/LICENSE +0 -0
- {jaf_py-2.5.3.dist-info → jaf_py-2.5.5.dist-info}/top_level.txt +0 -0
jaf/server/server.py
CHANGED
|
@@ -18,6 +18,7 @@ from fastapi.responses import StreamingResponse
|
|
|
18
18
|
|
|
19
19
|
from ..core.engine import run
|
|
20
20
|
from ..core.streaming import run_streaming
|
|
21
|
+
from ..core.regeneration import regenerate_conversation, get_regeneration_points
|
|
21
22
|
from ..core.types import (
|
|
22
23
|
ApprovalValue,
|
|
23
24
|
CompletedOutcome,
|
|
@@ -29,6 +30,8 @@ from ..core.types import (
|
|
|
29
30
|
RunState,
|
|
30
31
|
create_run_id,
|
|
31
32
|
create_trace_id,
|
|
33
|
+
create_message_id,
|
|
34
|
+
RegenerationRequest,
|
|
32
35
|
)
|
|
33
36
|
from ..memory.types import MemoryConfig
|
|
34
37
|
from .types import (
|
|
@@ -52,8 +55,15 @@ from .types import (
|
|
|
52
55
|
PendingApprovalData,
|
|
53
56
|
PendingApprovalsData,
|
|
54
57
|
PendingApprovalsResponse,
|
|
58
|
+
RegenerationHttpRequest,
|
|
59
|
+
RegenerationData,
|
|
60
|
+
RegenerationResponse,
|
|
61
|
+
RegenerationPointData,
|
|
62
|
+
RegenerationHistoryData,
|
|
63
|
+
RegenerationHistoryResponse,
|
|
55
64
|
ServerConfig,
|
|
56
65
|
ToolCallInterruption,
|
|
66
|
+
validate_regeneration_request,
|
|
57
67
|
)
|
|
58
68
|
|
|
59
69
|
Ctx = TypeVar('Ctx')
|
|
@@ -854,4 +864,157 @@ def create_jaf_server(config: ServerConfig[Ctx]) -> FastAPI:
|
|
|
854
864
|
}
|
|
855
865
|
)
|
|
856
866
|
|
|
867
|
+
# Regeneration endpoints
|
|
868
|
+
if config.default_memory_provider:
|
|
869
|
+
@app.post("/conversations/{conversation_id}/regenerate", response_model=RegenerationResponse)
|
|
870
|
+
async def regenerate_conversation_endpoint(conversation_id: str, request: RegenerationHttpRequest):
|
|
871
|
+
"""Regenerate conversation from a specific message."""
|
|
872
|
+
request_start_time = time.time()
|
|
873
|
+
|
|
874
|
+
try:
|
|
875
|
+
# Validate agent exists
|
|
876
|
+
if request.agent_name not in config.agent_registry:
|
|
877
|
+
return RegenerationResponse(
|
|
878
|
+
success=False,
|
|
879
|
+
error=f"Agent '{request.agent_name}' not found. Available agents: {', '.join(config.agent_registry.keys())}"
|
|
880
|
+
)
|
|
881
|
+
|
|
882
|
+
# Create regeneration request
|
|
883
|
+
regen_request = RegenerationRequest(
|
|
884
|
+
conversation_id=conversation_id,
|
|
885
|
+
message_id=create_message_id(request.message_id),
|
|
886
|
+
context=request.context
|
|
887
|
+
)
|
|
888
|
+
|
|
889
|
+
# Create run config with memory
|
|
890
|
+
memory_config = MemoryConfig(
|
|
891
|
+
provider=config.default_memory_provider,
|
|
892
|
+
auto_store=True,
|
|
893
|
+
store_on_completion=True
|
|
894
|
+
)
|
|
895
|
+
|
|
896
|
+
run_config_with_memory = replace(
|
|
897
|
+
config.run_config,
|
|
898
|
+
memory=memory_config,
|
|
899
|
+
conversation_id=conversation_id,
|
|
900
|
+
max_turns=request.max_turns or 10
|
|
901
|
+
)
|
|
902
|
+
|
|
903
|
+
# Execute regeneration
|
|
904
|
+
result = await regenerate_conversation(
|
|
905
|
+
regen_request,
|
|
906
|
+
run_config_with_memory,
|
|
907
|
+
request.context or {},
|
|
908
|
+
request.agent_name
|
|
909
|
+
)
|
|
910
|
+
|
|
911
|
+
# Convert result to HTTP format
|
|
912
|
+
http_messages = [_convert_core_message_to_http(msg) for msg in result.final_state.messages]
|
|
913
|
+
|
|
914
|
+
# Create outcome data
|
|
915
|
+
if isinstance(result.outcome, CompletedOutcome):
|
|
916
|
+
outcome_data = BaseOutcomeData(
|
|
917
|
+
status='completed',
|
|
918
|
+
output=result.outcome.output
|
|
919
|
+
)
|
|
920
|
+
elif isinstance(result.outcome, ErrorOutcome):
|
|
921
|
+
error_info = result.outcome.error
|
|
922
|
+
outcome_data = BaseOutcomeData(
|
|
923
|
+
status='error',
|
|
924
|
+
error={
|
|
925
|
+
'type': error_info.__class__.__name__,
|
|
926
|
+
'message': str(error_info)
|
|
927
|
+
}
|
|
928
|
+
)
|
|
929
|
+
elif isinstance(result.outcome, InterruptedOutcome):
|
|
930
|
+
interruptions = []
|
|
931
|
+
for interruption in result.outcome.interruptions:
|
|
932
|
+
if hasattr(interruption, 'tool_call') and hasattr(interruption, 'type'):
|
|
933
|
+
tool_call_data = ToolCallInterruption(
|
|
934
|
+
id=interruption.tool_call.id,
|
|
935
|
+
function={
|
|
936
|
+
'name': interruption.tool_call.function.name,
|
|
937
|
+
'arguments': interruption.tool_call.function.arguments
|
|
938
|
+
}
|
|
939
|
+
)
|
|
940
|
+
interruptions.append(InterruptionData(
|
|
941
|
+
type='tool_approval',
|
|
942
|
+
tool_call=tool_call_data,
|
|
943
|
+
session_id=interruption.session_id or str(result.final_state.run_id)
|
|
944
|
+
))
|
|
945
|
+
|
|
946
|
+
outcome_data = InterruptedOutcomeData(
|
|
947
|
+
status='interrupted',
|
|
948
|
+
interruptions=interruptions
|
|
949
|
+
)
|
|
950
|
+
else:
|
|
951
|
+
outcome_data = BaseOutcomeData(status='error', error='Unknown outcome type')
|
|
952
|
+
|
|
953
|
+
# Get regeneration metadata from conversation
|
|
954
|
+
conversation_result = await config.default_memory_provider.get_conversation(conversation_id)
|
|
955
|
+
regeneration_id = f"regen_{int(time.time() * 1000)}_{request.message_id}"
|
|
956
|
+
original_message_count = 0
|
|
957
|
+
truncated_at_index = 0
|
|
958
|
+
|
|
959
|
+
if hasattr(conversation_result, 'data') and conversation_result.data:
|
|
960
|
+
conversation_data = conversation_result.data
|
|
961
|
+
regeneration_points = conversation_data.metadata.get('regeneration_points', []) if conversation_data.metadata else []
|
|
962
|
+
if regeneration_points:
|
|
963
|
+
latest_regen = regeneration_points[-1]
|
|
964
|
+
original_message_count = latest_regen.get('original_message_count', len(conversation_data.messages))
|
|
965
|
+
truncated_at_index = latest_regen.get('truncated_at_index', 0)
|
|
966
|
+
regeneration_id = latest_regen.get('regeneration_id', regeneration_id)
|
|
967
|
+
|
|
968
|
+
return RegenerationResponse(
|
|
969
|
+
success=True,
|
|
970
|
+
data=RegenerationData(
|
|
971
|
+
regeneration_id=regeneration_id,
|
|
972
|
+
conversation_id=conversation_id,
|
|
973
|
+
original_message_count=original_message_count,
|
|
974
|
+
truncated_at_index=truncated_at_index,
|
|
975
|
+
regenerated_message_id=request.message_id,
|
|
976
|
+
messages=http_messages,
|
|
977
|
+
outcome=outcome_data,
|
|
978
|
+
turn_count=result.final_state.turn_count,
|
|
979
|
+
execution_time_ms=int((time.time() - request_start_time) * 1000)
|
|
980
|
+
)
|
|
981
|
+
)
|
|
982
|
+
|
|
983
|
+
except Exception as e:
|
|
984
|
+
return RegenerationResponse(success=False, error=str(e))
|
|
985
|
+
|
|
986
|
+
@app.get("/conversations/{conversation_id}/regeneration-history", response_model=RegenerationHistoryResponse)
|
|
987
|
+
async def get_regeneration_history(conversation_id: str):
|
|
988
|
+
"""Get regeneration history for a conversation."""
|
|
989
|
+
try:
|
|
990
|
+
regeneration_points = await get_regeneration_points(conversation_id, config.run_config)
|
|
991
|
+
|
|
992
|
+
if regeneration_points is None:
|
|
993
|
+
return RegenerationHistoryResponse(
|
|
994
|
+
success=False,
|
|
995
|
+
error="Failed to get regeneration history"
|
|
996
|
+
)
|
|
997
|
+
|
|
998
|
+
# Convert to response format
|
|
999
|
+
regeneration_data = []
|
|
1000
|
+
for point in regeneration_points:
|
|
1001
|
+
regeneration_data.append(RegenerationPointData(
|
|
1002
|
+
regeneration_id=point.get('regeneration_id', ''),
|
|
1003
|
+
message_id=point.get('message_id', ''),
|
|
1004
|
+
timestamp=point.get('timestamp', 0),
|
|
1005
|
+
original_message_count=point.get('original_message_count', 0),
|
|
1006
|
+
truncated_at_index=point.get('truncated_at_index', 0)
|
|
1007
|
+
))
|
|
1008
|
+
|
|
1009
|
+
return RegenerationHistoryResponse(
|
|
1010
|
+
success=True,
|
|
1011
|
+
data=RegenerationHistoryData(
|
|
1012
|
+
conversation_id=conversation_id,
|
|
1013
|
+
regeneration_points=regeneration_data
|
|
1014
|
+
)
|
|
1015
|
+
)
|
|
1016
|
+
|
|
1017
|
+
except Exception as e:
|
|
1018
|
+
return RegenerationHistoryResponse(success=False, error=str(e))
|
|
1019
|
+
|
|
857
1020
|
return app
|
jaf/server/types.py
CHANGED
|
@@ -11,7 +11,7 @@ import base64
|
|
|
11
11
|
|
|
12
12
|
from pydantic import BaseModel, Field, field_validator, model_validator
|
|
13
13
|
|
|
14
|
-
from ..core.types import Agent, RunConfig, Attachment, MessageContentPart, get_text_content
|
|
14
|
+
from ..core.types import Agent, RunConfig, Attachment, MessageContentPart, get_text_content, MessageId, RegenerationRequest
|
|
15
15
|
from ..memory.types import MemoryProvider
|
|
16
16
|
|
|
17
17
|
Ctx = TypeVar('Ctx')
|
|
@@ -267,8 +267,56 @@ class PendingApprovalsResponse(BaseModel):
|
|
|
267
267
|
data: Optional[PendingApprovalsData] = None
|
|
268
268
|
error: Optional[str] = None
|
|
269
269
|
|
|
270
|
+
# Regeneration types
|
|
271
|
+
class RegenerationHttpRequest(BaseModel):
|
|
272
|
+
"""HTTP request format for conversation regeneration."""
|
|
273
|
+
message_id: str = Field(..., description="ID of the message to regenerate from")
|
|
274
|
+
agent_name: str = Field(..., description="Name of the agent to use for regeneration")
|
|
275
|
+
context: Optional[Dict[str, Any]] = Field(default=None, description="Optional context override for regeneration")
|
|
276
|
+
max_turns: Optional[int] = Field(default=10, description="Maximum number of turns for regeneration")
|
|
277
|
+
|
|
278
|
+
class RegenerationData(BaseModel):
|
|
279
|
+
"""Data for successful regeneration response."""
|
|
280
|
+
regeneration_id: str
|
|
281
|
+
conversation_id: str
|
|
282
|
+
original_message_count: int
|
|
283
|
+
truncated_at_index: int
|
|
284
|
+
regenerated_message_id: str
|
|
285
|
+
messages: List[HttpMessage]
|
|
286
|
+
outcome: BaseOutcomeData
|
|
287
|
+
turn_count: int
|
|
288
|
+
execution_time_ms: int
|
|
289
|
+
|
|
290
|
+
class RegenerationResponse(BaseModel):
|
|
291
|
+
"""Response format for regeneration endpoints."""
|
|
292
|
+
success: bool
|
|
293
|
+
data: Optional[RegenerationData] = None
|
|
294
|
+
error: Optional[str] = None
|
|
295
|
+
|
|
296
|
+
class RegenerationPointData(BaseModel):
|
|
297
|
+
"""Data for a regeneration point."""
|
|
298
|
+
regeneration_id: str
|
|
299
|
+
message_id: str
|
|
300
|
+
timestamp: int
|
|
301
|
+
original_message_count: int
|
|
302
|
+
truncated_at_index: int
|
|
303
|
+
|
|
304
|
+
class RegenerationHistoryData(BaseModel):
|
|
305
|
+
"""Data for regeneration history response."""
|
|
306
|
+
conversation_id: str
|
|
307
|
+
regeneration_points: List[RegenerationPointData]
|
|
308
|
+
|
|
309
|
+
class RegenerationHistoryResponse(BaseModel):
|
|
310
|
+
"""Response format for regeneration history endpoint."""
|
|
311
|
+
success: bool
|
|
312
|
+
data: Optional[RegenerationHistoryData] = None
|
|
313
|
+
error: Optional[str] = None
|
|
270
314
|
|
|
271
315
|
# Validation schemas
|
|
272
316
|
def validate_chat_request(data: Dict[str, Any]) -> ChatRequest:
|
|
273
317
|
"""Validate and parse a chat request."""
|
|
274
318
|
return ChatRequest.model_validate(data)
|
|
319
|
+
|
|
320
|
+
def validate_regeneration_request(data: Dict[str, Any]) -> RegenerationHttpRequest:
|
|
321
|
+
"""Validate and parse a regeneration request."""
|
|
322
|
+
return RegenerationHttpRequest.model_validate(data)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jaf-py
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.5
|
|
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=jzou4ny01tsRBZAb-ojUf4pjyu5LA32FRDt_QiHjSPs,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
|
|
@@ -42,7 +42,7 @@ jaf/core/__init__.py,sha256=1VHV2-a1oJXIWcg8n5G5g2cmjw2QXv7OezncNB59KLw,1988
|
|
|
42
42
|
jaf/core/agent_tool.py,sha256=tfLNaTIcOZ0dR9GBP1AHLPkLExm_dLbURnVIN4R84FQ,11806
|
|
43
43
|
jaf/core/analytics.py,sha256=zFHIWqWal0bbEFCmJDc4DKeM0Ja7b_D19PqVaBI12pA,23338
|
|
44
44
|
jaf/core/composition.py,sha256=IVxRO1Q9nK7JRH32qQ4p8WMIUu66BhqPNrlTNMGFVwE,26317
|
|
45
|
-
jaf/core/engine.py,sha256=
|
|
45
|
+
jaf/core/engine.py,sha256=gv2nnkiWbqD54ru7NE3-c__DjOgp4OtPSoY9ApaBZIc,61009
|
|
46
46
|
jaf/core/errors.py,sha256=5fwTNhkojKRQ4wZj3lZlgDnAsrYyjYOwXJkIr5EGNUc,5539
|
|
47
47
|
jaf/core/guardrails.py,sha256=nv7pQuCx7-9DDZrecWO1DsDqFoujL81FBDrafOsXgcI,26179
|
|
48
48
|
jaf/core/handoff.py,sha256=ttjOQ6CSl34J4T_1ejdmq78gZ-ve07_IQE_DAbz2bmo,6002
|
|
@@ -50,22 +50,23 @@ jaf/core/parallel_agents.py,sha256=ahwYoTnkrF4xQgV-hjc5sUaWhQWQFENMZG5riNa_Ieg,1
|
|
|
50
50
|
jaf/core/performance.py,sha256=jedQmTEkrKMD6_Aw1h8PdG-5TsdYSFFT7Or6k5dmN2g,9974
|
|
51
51
|
jaf/core/proxy.py,sha256=_WM3cpRlSQLYpgSBrnY30UPMe2iZtlqDQ65kppE-WY0,4609
|
|
52
52
|
jaf/core/proxy_helpers.py,sha256=i7a5fAX9rLmO4FMBX51-yRkTFwfWedzQNgnLmeLUd_A,4370
|
|
53
|
+
jaf/core/regeneration.py,sha256=jlV2PwobP_kAhafaP8zuwZcYyZiuh7QbWgA9_4ST8xM,17904
|
|
53
54
|
jaf/core/state.py,sha256=oNCVXPWLkqnBQObdQX10TcmZ0eOF3wKG6DtL3kF6ohw,9649
|
|
54
55
|
jaf/core/streaming.py,sha256=h_lYHQA9ee_D5QsDO9-Vhevgi7rFXPslPzd9605AJGo,17034
|
|
55
56
|
jaf/core/tool_results.py,sha256=-bTOqOX02lMyslp5Z4Dmuhx0cLd5o7kgR88qK2HO_sw,11323
|
|
56
57
|
jaf/core/tools.py,sha256=84N9A7QQ3xxcOs2eUUot3nmCnt5i7iZT9VwkuzuFBxQ,16274
|
|
57
|
-
jaf/core/tracing.py,sha256=
|
|
58
|
-
jaf/core/types.py,sha256=
|
|
58
|
+
jaf/core/tracing.py,sha256=GNOJ8cJ-1kIsrvx_WUEhihy6T-hYk6i5MFB_UVGAcwU,53367
|
|
59
|
+
jaf/core/types.py,sha256=xXkSV2ZE9oQea3JrU9XfWFvIHWUbZHHftJaZV-UAwHg,32860
|
|
59
60
|
jaf/core/workflows.py,sha256=Ul-82gzjIXtkhnSMSPv-8igikjkMtW1EBo9yrfodtvI,26294
|
|
60
61
|
jaf/memory/__init__.py,sha256=-L98xlvihurGAzF0DnXtkueDVvO_wV2XxxEwAWdAj50,1400
|
|
61
62
|
jaf/memory/approval_storage.py,sha256=HHZ_b57kIthdR53QE5XNSII9xy1Cg-1cFUCSAZ8A4Rk,11083
|
|
62
63
|
jaf/memory/factory.py,sha256=Fh6JyvQtCKe38DZV5-NnC9vPRCvzBgSSPFIGaX7Nt5E,2958
|
|
63
|
-
jaf/memory/types.py,sha256=
|
|
64
|
-
jaf/memory/utils.py,sha256=
|
|
64
|
+
jaf/memory/types.py,sha256=pEFaofSISJ_FipiNpju0qPImpB_Pqy8yY5MSpMMi59E,9614
|
|
65
|
+
jaf/memory/utils.py,sha256=TTiLdP6-fEzy2GjF-KyimOLfeEla8bIHcscAETA4_Ic,6966
|
|
65
66
|
jaf/memory/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
66
|
-
jaf/memory/providers/in_memory.py,sha256=
|
|
67
|
-
jaf/memory/providers/postgres.py,sha256=
|
|
68
|
-
jaf/memory/providers/redis.py,sha256=
|
|
67
|
+
jaf/memory/providers/in_memory.py,sha256=aL1a1vttvu6WKmJFWMN6T6OMdpdOaQL0a0tkq2YUfks,20413
|
|
68
|
+
jaf/memory/providers/postgres.py,sha256=gxGnoQyBeYMg3GVE1Y6aN45w-RLgyefOJBzhVK3kF84,20989
|
|
69
|
+
jaf/memory/providers/redis.py,sha256=eSUmR66j_DyOE13Hug9bC2DdK1n6D85ERYNPcZFpyZs,17106
|
|
69
70
|
jaf/plugins/__init__.py,sha256=8GMtLld3UpkJVJ05gfVthw8tVXW0ALL6e6s88cKiCwY,796
|
|
70
71
|
jaf/plugins/base.py,sha256=clQohPxT19zj-AjRtDoevE26xS5-cm7qdUOW2VX2InY,12575
|
|
71
72
|
jaf/policies/__init__.py,sha256=tfbUgIPMwMKvZsyDItP_zvbhGXGY5scKSo78LIomgDU,416
|
|
@@ -76,8 +77,8 @@ jaf/providers/mcp.py,sha256=WxcC8gUFpDBBYyhorMcc1jHq3xMDMBtnwyRPthfL0S0,13074
|
|
|
76
77
|
jaf/providers/model.py,sha256=bN2Hhr0N3soZzMrCdJ1pJa4rvo80oedCphDPcNgrVMY,39336
|
|
77
78
|
jaf/server/__init__.py,sha256=fMPnLZBRm6t3yQrr7-PnoHAQ8qj9o6Z1AJLM1M6bIS0,392
|
|
78
79
|
jaf/server/main.py,sha256=CTb0ywbPIq9ELfay5MKChVR7BpIQOoEbPjPfpzo2aBQ,2152
|
|
79
|
-
jaf/server/server.py,sha256=
|
|
80
|
-
jaf/server/types.py,sha256=
|
|
80
|
+
jaf/server/server.py,sha256=cbdhVTPoWa7rVIX3DDLoXjppeGTKQWNFj3NA1jrZN88,46830
|
|
81
|
+
jaf/server/types.py,sha256=Evsq9yaZp_mleGRBXCj39fRKBCwBaBDbORCB2x9r5aw,12405
|
|
81
82
|
jaf/utils/__init__.py,sha256=4Lte7HPIpmEuGvWd9lSH9gljV11wy-yNFjECPhcejAY,1236
|
|
82
83
|
jaf/utils/attachments.py,sha256=9xNzzQanCwJnBR1L6P79YQtbuRupiDluDn46SYUlHok,13542
|
|
83
84
|
jaf/utils/document_processor.py,sha256=FSALtq-RLMWJPmxRSDs32Nys4XAvacSbRf211-mjIeA,20150
|
|
@@ -87,9 +88,9 @@ jaf/visualization/functional_core.py,sha256=zedMDZbvjuOugWwnh6SJ2stvRNQX1Hlkb9Ab
|
|
|
87
88
|
jaf/visualization/graphviz.py,sha256=WTOM6UP72-lVKwI4_SAr5-GCC3ouckxHv88ypCDQWJ0,12056
|
|
88
89
|
jaf/visualization/imperative_shell.py,sha256=GpMrAlMnLo2IQgyB2nardCz09vMvAzaYI46MyrvJ0i4,2593
|
|
89
90
|
jaf/visualization/types.py,sha256=QQcbVeQJLuAOXk8ynd08DXIS-PVCnv3R-XVE9iAcglw,1389
|
|
90
|
-
jaf_py-2.5.
|
|
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.
|
|
91
|
+
jaf_py-2.5.5.dist-info/licenses/LICENSE,sha256=LXUQBJxdyr-7C4bk9cQBwvsF_xwA-UVstDTKabpcjlI,1063
|
|
92
|
+
jaf_py-2.5.5.dist-info/METADATA,sha256=QavZuyRtYw55yL1NQOmYfLIMxLhTu_V5yZaHOKOY4gY,27743
|
|
93
|
+
jaf_py-2.5.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
94
|
+
jaf_py-2.5.5.dist-info/entry_points.txt,sha256=OtIJeNJpb24kgGrqRx9szGgDx1vL9ayq8uHErmu7U5w,41
|
|
95
|
+
jaf_py-2.5.5.dist-info/top_level.txt,sha256=Xu1RZbGaM4_yQX7bpalo881hg7N_dybaOW282F15ruE,4
|
|
96
|
+
jaf_py-2.5.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|