langchain-agentx-python 2.2.1__py3-none-any.whl → 2.2.3__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.
- langchain_agentx/__init__.py +1 -1
- langchain_agentx/observability/events/agent_event_projector.py +36 -19
- langchain_agentx/observability/events/compact_event_gate.py +152 -0
- langchain_agentx/tools/grep/backend.py +20 -5
- {langchain_agentx_python-2.2.1.dist-info → langchain_agentx_python-2.2.3.dist-info}/METADATA +1 -1
- {langchain_agentx_python-2.2.1.dist-info → langchain_agentx_python-2.2.3.dist-info}/RECORD +9 -8
- {langchain_agentx_python-2.2.1.dist-info → langchain_agentx_python-2.2.3.dist-info}/LICENSE +0 -0
- {langchain_agentx_python-2.2.1.dist-info → langchain_agentx_python-2.2.3.dist-info}/WHEEL +0 -0
- {langchain_agentx_python-2.2.1.dist-info → langchain_agentx_python-2.2.3.dist-info}/top_level.txt +0 -0
langchain_agentx/__init__.py
CHANGED
|
@@ -51,6 +51,12 @@ from langchain_agentx.observability.events.agent_defaults import DEFAULT_AGENT_T
|
|
|
51
51
|
from langchain_agentx.observability.events.subagent_window_text_guard import (
|
|
52
52
|
SubagentWindowTextGuard,
|
|
53
53
|
)
|
|
54
|
+
from langchain_agentx.observability.events.compact_event_gate import (
|
|
55
|
+
beneficial_light_stage_names,
|
|
56
|
+
extract_compaction_meta_from_chain_end_data,
|
|
57
|
+
is_user_visible_compact,
|
|
58
|
+
light_only_with_benefit,
|
|
59
|
+
)
|
|
54
60
|
from langchain_agentx.observability.events.tool_call_id_resolver import (
|
|
55
61
|
ToolCallIdResolver,
|
|
56
62
|
)
|
|
@@ -121,8 +127,7 @@ class LangchainAgentEventType(Enum):
|
|
|
121
127
|
FINISH_STEP = "finish-step"
|
|
122
128
|
HOOK_PROGRESS = "hook-progress"
|
|
123
129
|
HOOK_FINISHED = "hook-finished"
|
|
124
|
-
|
|
125
|
-
COMPACT_END = "compact-end"
|
|
130
|
+
COMPACT_BOUNDARY = "compact-boundary"
|
|
126
131
|
MEMORY_SAVED = "memory-saved"
|
|
127
132
|
SUBAGENT_START = "subagent-start"
|
|
128
133
|
SUBAGENT_END = "subagent-end"
|
|
@@ -396,12 +401,7 @@ class AgentEventProjector:
|
|
|
396
401
|
step_index=self.state.step_index or None,
|
|
397
402
|
)
|
|
398
403
|
|
|
399
|
-
|
|
400
|
-
yield self._event(
|
|
401
|
-
event_type=LangchainAgentEventType.COMPACT_START,
|
|
402
|
-
data={},
|
|
403
|
-
step_index=self.state.step_index or None,
|
|
404
|
-
)
|
|
404
|
+
# D-CMP-EVT:不在 start 发 compact(CC 无 start/end;事后单边界)
|
|
405
405
|
|
|
406
406
|
def _build_loop_observation_payload(self) -> Dict[str, Any]:
|
|
407
407
|
snap = self.state.last_loop_snapshot or {}
|
|
@@ -752,7 +752,6 @@ class AgentEventProjector:
|
|
|
752
752
|
result["tokens_freed"] = meta.get("tokens_freed_sum")
|
|
753
753
|
|
|
754
754
|
stages = meta.get("stages")
|
|
755
|
-
autocompact_found = False
|
|
756
755
|
microcompact_found = False
|
|
757
756
|
|
|
758
757
|
if isinstance(stages, list):
|
|
@@ -761,7 +760,6 @@ class AgentEventProjector:
|
|
|
761
760
|
name = s.get("name")
|
|
762
761
|
extra = s.get("extra") or {}
|
|
763
762
|
if name == "autocompact":
|
|
764
|
-
autocompact_found = True
|
|
765
763
|
result["autocompact_mode"] = extra.get("autocompact_mode")
|
|
766
764
|
result["folded_messages"] = extra.get("folded_messages")
|
|
767
765
|
result["messages_summarized"] = extra.get("folded_messages")
|
|
@@ -782,10 +780,12 @@ class AgentEventProjector:
|
|
|
782
780
|
break
|
|
783
781
|
|
|
784
782
|
if "compact_type" not in result:
|
|
785
|
-
|
|
783
|
+
mode = result.get("autocompact_mode")
|
|
784
|
+
if isinstance(mode, str) and mode:
|
|
786
785
|
result["compact_type"] = "autocompact"
|
|
787
|
-
|
|
786
|
+
elif microcompact_found:
|
|
788
787
|
result["compact_type"] = "microcompact"
|
|
788
|
+
# 不再用「stages 出现过 autocompact 名」回落为 autocompact(假阳性)
|
|
789
789
|
|
|
790
790
|
if "summary" not in result:
|
|
791
791
|
messages = output.get("messages")
|
|
@@ -848,13 +848,30 @@ class AgentEventProjector:
|
|
|
848
848
|
step_index=self.state.step_index or None,
|
|
849
849
|
)
|
|
850
850
|
|
|
851
|
-
if self.
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
851
|
+
if self._is_compact_node(name):
|
|
852
|
+
meta = extract_compaction_meta_from_chain_end_data(data)
|
|
853
|
+
if is_user_visible_compact(meta):
|
|
854
|
+
if self.enable_compact_events:
|
|
855
|
+
compact_data = self._extract_compact_summary(data)
|
|
856
|
+
if "trigger" not in compact_data:
|
|
857
|
+
compact_data["trigger"] = "auto"
|
|
858
|
+
yield self._event(
|
|
859
|
+
event_type=LangchainAgentEventType.COMPACT_BOUNDARY,
|
|
860
|
+
data=compact_data,
|
|
861
|
+
step_index=self.state.step_index or None,
|
|
862
|
+
)
|
|
863
|
+
elif light_only_with_benefit(meta):
|
|
864
|
+
# D-CMP-EVT-7:对齐 CC logForDebugging;不受 enable_compact_events 关闭影响
|
|
865
|
+
freed = None
|
|
866
|
+
if isinstance(meta, dict):
|
|
867
|
+
freed = meta.get("tokens_freed_sum")
|
|
868
|
+
stages = beneficial_light_stage_names(meta)
|
|
869
|
+
logger.debug(
|
|
870
|
+
"compact light-only: tokens_freed_sum=%s stages=%s "
|
|
871
|
+
"(no public compact-boundary; align CC logForDebugging)",
|
|
872
|
+
freed,
|
|
873
|
+
stages or None,
|
|
874
|
+
)
|
|
858
875
|
|
|
859
876
|
if name == self.state.graph_name:
|
|
860
877
|
if self.enable_reasoning_events and self.state.is_reasoning_active:
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""
|
|
2
|
+
compact_event_gate.py — compact 公共事件门闩(对齐 CC compact_boundary)
|
|
3
|
+
|
|
4
|
+
职责:
|
|
5
|
+
- 从 compaction_pipeline_meta 判定是否用户可见真压缩 / light-only 有收益
|
|
6
|
+
- 供 agent_event_projector 发射 compact-boundary 或 logger.debug
|
|
7
|
+
|
|
8
|
+
链路位置:
|
|
9
|
+
- Layer 3: observability/events 投影门闩(不改 L0 压缩流水线)
|
|
10
|
+
|
|
11
|
+
当前裁剪范围:
|
|
12
|
+
- 仅 meta 谓词;不创建 SSE 以外的事件类型
|
|
13
|
+
- session_memory applied 仅识别显式标记(字段可后续扩展)
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import Any, Optional
|
|
19
|
+
|
|
20
|
+
from langchain_agentx.loop.exit.query_source import QuerySource
|
|
21
|
+
|
|
22
|
+
# 实际折叠上下文的 autocompact_mode(不含仅 skipped)
|
|
23
|
+
APPLIED_AUTOCOMPACT_MODES: frozenset[str] = frozenset(
|
|
24
|
+
{
|
|
25
|
+
"llm",
|
|
26
|
+
"prune",
|
|
27
|
+
"prune_blocked_llm",
|
|
28
|
+
}
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
_LIGHT_STAGE_NAMES: frozenset[str] = frozenset(
|
|
32
|
+
{
|
|
33
|
+
"tool_result_budget",
|
|
34
|
+
"snip",
|
|
35
|
+
"microcompact",
|
|
36
|
+
"collapse",
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _as_dict(meta: Any) -> Optional[dict[str, Any]]:
|
|
42
|
+
return meta if isinstance(meta, dict) else None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _stage_extra(stage: dict[str, Any]) -> dict[str, Any]:
|
|
46
|
+
extra = stage.get("extra")
|
|
47
|
+
return extra if isinstance(extra, dict) else {}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _positive_number(value: Any) -> bool:
|
|
51
|
+
if value is None:
|
|
52
|
+
return False
|
|
53
|
+
try:
|
|
54
|
+
return float(value) > 0
|
|
55
|
+
except (TypeError, ValueError):
|
|
56
|
+
return False
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def is_user_visible_compact(meta: Any) -> bool:
|
|
60
|
+
"""真压缩已应用 → 应对齐 CC 发一条 compact-boundary。
|
|
61
|
+
|
|
62
|
+
禁止用 tokens_freed_sum / stages 仅出现 autocompact 名 / compact_type 回落判定。
|
|
63
|
+
"""
|
|
64
|
+
m = _as_dict(meta)
|
|
65
|
+
if m is None:
|
|
66
|
+
return False
|
|
67
|
+
|
|
68
|
+
# Session / 手动:L0 现网键(factory session_memory 路径无 stages[])
|
|
69
|
+
if m.get("session_memory_compact_applied") is True:
|
|
70
|
+
return True
|
|
71
|
+
if m.get("manual_compact_applied") is True:
|
|
72
|
+
return True
|
|
73
|
+
if m.get("session_memory_compaction") == "applied":
|
|
74
|
+
return True
|
|
75
|
+
if m.get("autocompact_mode") == QuerySource.SESSION_MEMORY:
|
|
76
|
+
return True
|
|
77
|
+
|
|
78
|
+
stages = m.get("stages")
|
|
79
|
+
if not isinstance(stages, list):
|
|
80
|
+
return False
|
|
81
|
+
|
|
82
|
+
for stage in stages:
|
|
83
|
+
if not isinstance(stage, dict):
|
|
84
|
+
continue
|
|
85
|
+
name = stage.get("name")
|
|
86
|
+
extra = _stage_extra(stage)
|
|
87
|
+
if name == "autocompact":
|
|
88
|
+
mode = extra.get("autocompact_mode")
|
|
89
|
+
if isinstance(mode, str) and mode in APPLIED_AUTOCOMPACT_MODES:
|
|
90
|
+
return True
|
|
91
|
+
if name == QuerySource.SESSION_MEMORY and extra.get("applied") is True:
|
|
92
|
+
return True
|
|
93
|
+
return False
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def light_only_with_benefit(meta: Any) -> bool:
|
|
97
|
+
"""非用户可见,但有轻量 stage(或 sum)释放 token → 应对齐 CC logForDebugging。"""
|
|
98
|
+
if is_user_visible_compact(meta):
|
|
99
|
+
return False
|
|
100
|
+
m = _as_dict(meta)
|
|
101
|
+
if m is None:
|
|
102
|
+
return False
|
|
103
|
+
|
|
104
|
+
stages = m.get("stages")
|
|
105
|
+
if isinstance(stages, list):
|
|
106
|
+
for stage in stages:
|
|
107
|
+
if not isinstance(stage, dict):
|
|
108
|
+
continue
|
|
109
|
+
if _positive_number(stage.get("tokens_freed")):
|
|
110
|
+
return True
|
|
111
|
+
# micro 规范化标记但 tokens 估计可能为 0:仍视为有 light 动作时可记
|
|
112
|
+
name = stage.get("name")
|
|
113
|
+
extra = _stage_extra(stage)
|
|
114
|
+
if name == "microcompact" and extra.get("microcompact_normalized"):
|
|
115
|
+
return True
|
|
116
|
+
|
|
117
|
+
return _positive_number(m.get("tokens_freed_sum"))
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def beneficial_light_stage_names(meta: Any) -> list[str]:
|
|
121
|
+
"""有收益的轻量 stage 名(供 debug 文案)。"""
|
|
122
|
+
m = _as_dict(meta)
|
|
123
|
+
if m is None:
|
|
124
|
+
return []
|
|
125
|
+
names: list[str] = []
|
|
126
|
+
stages = m.get("stages")
|
|
127
|
+
if not isinstance(stages, list):
|
|
128
|
+
return names
|
|
129
|
+
for stage in stages:
|
|
130
|
+
if not isinstance(stage, dict):
|
|
131
|
+
continue
|
|
132
|
+
name = stage.get("name")
|
|
133
|
+
if not isinstance(name, str):
|
|
134
|
+
continue
|
|
135
|
+
extra = _stage_extra(stage)
|
|
136
|
+
freed = _positive_number(stage.get("tokens_freed"))
|
|
137
|
+
micro = name == "microcompact" and bool(extra.get("microcompact_normalized"))
|
|
138
|
+
if freed or micro:
|
|
139
|
+
if name in _LIGHT_STAGE_NAMES or freed or micro:
|
|
140
|
+
names.append(name)
|
|
141
|
+
return names
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def extract_compaction_meta_from_chain_end_data(data: Any) -> Optional[dict[str, Any]]:
|
|
145
|
+
"""从 on_chain_end data 取出 compaction_pipeline_meta。"""
|
|
146
|
+
if not isinstance(data, dict):
|
|
147
|
+
return None
|
|
148
|
+
output = data.get("output")
|
|
149
|
+
if not isinstance(output, dict):
|
|
150
|
+
return None
|
|
151
|
+
meta = output.get("compaction_pipeline_meta")
|
|
152
|
+
return meta if isinstance(meta, dict) else None
|
|
@@ -28,6 +28,19 @@ from langchain_agentx.utils.subprocess_text import (
|
|
|
28
28
|
from .models import GrepOutputMode
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
def resolve_ripgrep_subprocess_cwd(search_path: str) -> str:
|
|
32
|
+
"""subprocess cwd 必须是目录;schema 允许 path 为文件时退到父目录。
|
|
33
|
+
|
|
34
|
+
Windows 上相对 glob 需要 cwd≈搜索根目录;但不能把文件路径直接当 cwd
|
|
35
|
+
(会 NotADirectoryError / Errno 20)。rg 命令行目标仍用原 search_path。
|
|
36
|
+
"""
|
|
37
|
+
real = os.path.realpath(search_path)
|
|
38
|
+
if os.path.isfile(real):
|
|
39
|
+
parent = os.path.dirname(real)
|
|
40
|
+
return parent if parent else os.sep
|
|
41
|
+
return real
|
|
42
|
+
|
|
43
|
+
|
|
31
44
|
class GrepTimeoutError(ToolRuntimeError):
|
|
32
45
|
def __init__(self, message: str) -> None:
|
|
33
46
|
super().__init__(message, code="GREP_TIMEOUT")
|
|
@@ -60,14 +73,16 @@ def run_ripgrep_lines(
|
|
|
60
73
|
对齐 CC ripgrep.ts:returncode 1 -> [];EAGAIN 时以 -j 1 重试一次。
|
|
61
74
|
供 RipgrepBackend 与 Glob 的 rg --files 列文件共用。
|
|
62
75
|
|
|
63
|
-
SDK 补充:``subprocess cwd
|
|
64
|
-
|
|
76
|
+
SDK 补充:``subprocess cwd`` 对齐搜索根目录(目录本身,或文件的父目录)。
|
|
77
|
+
CC 隐式依赖进程 cwd≈searchDir;编排布局 ``state_root≠repo`` 时须显式设 cwd,
|
|
78
|
+
否则 Windows 上目录前缀 glob(如 ``alpha/*``)误空。
|
|
65
79
|
|
|
66
80
|
若 ``cancel_event`` 非空,使用可中断子进程路径(``RgSubprocessController``),
|
|
67
81
|
不再走 ``text_runner.run``(便于测试 mock 时仅覆盖无取消路径)。
|
|
68
82
|
"""
|
|
69
|
-
|
|
70
|
-
|
|
83
|
+
search_target = os.path.realpath(search_path)
|
|
84
|
+
search_cwd = resolve_ripgrep_subprocess_cwd(search_path)
|
|
85
|
+
cmd = [rg_path, *args, search_target]
|
|
71
86
|
if cancel_event is not None:
|
|
72
87
|
if cancel_event.is_set():
|
|
73
88
|
raise GrepCancelledError("ripgrep cancelled before start")
|
|
@@ -321,7 +336,7 @@ class RipgrepBackend:
|
|
|
321
336
|
plugin_glob_exclusions=plugin_glob_exclusions,
|
|
322
337
|
)
|
|
323
338
|
cmd = [self._rg_path, *args, os.path.realpath(search_path)]
|
|
324
|
-
search_cwd =
|
|
339
|
+
search_cwd = resolve_ripgrep_subprocess_cwd(search_path)
|
|
325
340
|
if cancel_event is not None and cancel_event.is_set():
|
|
326
341
|
raise GrepCancelledError("ripgrep cancelled before start")
|
|
327
342
|
try:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
langchain_agentx/__init__.py,sha256=
|
|
1
|
+
langchain_agentx/__init__.py,sha256=bMHXxvdlfRUJK-ZT43f2Hgef2tNuOs5bc3mv-F4BQRc,1614
|
|
2
2
|
langchain_agentx/command/__init__.py,sha256=Ej260S5uFQcmEtGZQG_NH7BYjHoStrpBLtGUsBTxyZk,631
|
|
3
3
|
langchain_agentx/command/allowed_tools.py,sha256=TVA0VM8rm98H-QbLK_GRiX5RhEAZFxKawliMi4kk96A,3359
|
|
4
4
|
langchain_agentx/command/context.py,sha256=DIGOGPBw5UGDBm0WNNJlKx1h_9rCRmcdROv4DT61Qug,731
|
|
@@ -217,8 +217,9 @@ langchain_agentx/observability/evaluation/checkers/tool_behavior.py,sha256=o1nH8
|
|
|
217
217
|
langchain_agentx/observability/events/__init__.py,sha256=Zr9Iguf9XsJQLsCJy13YFdBtXHPEnI9aSWXWmA2MisA,1497
|
|
218
218
|
langchain_agentx/observability/events/accumulated_text_scope.py,sha256=M4OvuQTgReF8SFrOmr-M5vyOJpzfvxj_DKD5bVpGb70,3169
|
|
219
219
|
langchain_agentx/observability/events/agent_defaults.py,sha256=gmX0P__lux5xbCb8dtAlVCb3wZ7avaqFleoW4Q5anw4,1187
|
|
220
|
-
langchain_agentx/observability/events/agent_event_projector.py,sha256=
|
|
220
|
+
langchain_agentx/observability/events/agent_event_projector.py,sha256=Rktmy2D3qizCejAChbuOiAa06Tnup2Z6cVNATfrrxkU,63995
|
|
221
221
|
langchain_agentx/observability/events/api_retry_projection.py,sha256=XGb09sNOi6k1ZGW4YqMLBE8GDxNwNMprk62jV9TS9dQ,2433
|
|
222
|
+
langchain_agentx/observability/events/compact_event_gate.py,sha256=50RJemwB1lnQn_NFWOFSgU418ZUR8dbd_v0538PT7zM,4751
|
|
222
223
|
langchain_agentx/observability/events/factory.py,sha256=gqMATIK9tBQzaPWSPhCCSPuCq-WF562ZDTnFUaMm9Qc,1570
|
|
223
224
|
langchain_agentx/observability/events/finish_event_payload_composer.py,sha256=v7MyLNSZ_gR5u5WFxPJu_0MYNDvC9s9gI2iNNt9Vbr4,13189
|
|
224
225
|
langchain_agentx/observability/events/finish_outcome.py,sha256=igoueAwduzuuGDwg6u9AbBB-T2UBiqbUfNoxWCBYc_g,10401
|
|
@@ -580,7 +581,7 @@ langchain_agentx/tools/glob/rg_list_backend.py,sha256=gTyFQE0eYHl-7LkSdah76S8bQn
|
|
|
580
581
|
langchain_agentx/tools/glob/rg_pattern.py,sha256=YOV-1gdxC52vzdAwgz27l7mzPJvVuHqpqeWhiEnWQJs,1377
|
|
581
582
|
langchain_agentx/tools/glob/tool.py,sha256=m746Vl_aI9eFmrXYECkg16zMln9YPVxqjtijPlc5ALA,14868
|
|
582
583
|
langchain_agentx/tools/grep/__init__.py,sha256=AA9qa42Ap9tw6lPQkNgKzYmr4hu44eP93qVdyP-eFNU,162
|
|
583
|
-
langchain_agentx/tools/grep/backend.py,sha256=
|
|
584
|
+
langchain_agentx/tools/grep/backend.py,sha256=bzwRUJ_aZjs84oIG3l6IAVygGiLDyNsHPePiMaFMo-4,14539
|
|
584
585
|
langchain_agentx/tools/grep/models.py,sha256=6fTSux0COK06weQ7PWYqCGBQx60OaNtqC5q7xKtf5i0,3860
|
|
585
586
|
langchain_agentx/tools/grep/prompt.py,sha256=Euo1NErphk5WHxaKXwJH-1v7joblfwEFWHIYNthKkzo,1336
|
|
586
587
|
langchain_agentx/tools/grep/rg_subprocess_controller.py,sha256=ijMJnKPo7iEDFBz-_YipTiPusrL6OO2XbWxHUuwpMfA,4056
|
|
@@ -759,8 +760,8 @@ langchain_agentx/workspace/root_grant_manager.py,sha256=W3gy8HTevbERbXqIgRcjzOXO
|
|
|
759
760
|
langchain_agentx/workspace/tool_boundary.py,sha256=UDwX6swpSLsx9HNkYuuRRiV5o7ZZG_Bru2Yn0c5kNX8,5724
|
|
760
761
|
langchain_agentx/workspace/validators.py,sha256=tQt-6TOcL8Fw7Ig5ebA9S7vGWh1rby920eFW6x8Tk9E,1439
|
|
761
762
|
langchain_agentx/workspace/view.py,sha256=PGasqTaqhlD03SXXazHuw4RHfV681AIdlsYqL70pEjc,4774
|
|
762
|
-
langchain_agentx_python-2.2.
|
|
763
|
-
langchain_agentx_python-2.2.
|
|
764
|
-
langchain_agentx_python-2.2.
|
|
765
|
-
langchain_agentx_python-2.2.
|
|
766
|
-
langchain_agentx_python-2.2.
|
|
763
|
+
langchain_agentx_python-2.2.3.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
764
|
+
langchain_agentx_python-2.2.3.dist-info/METADATA,sha256=VcuvJI240NmP2VxSl2xxXD2BTvpnCLxnkXjg5aHzmQE,24250
|
|
765
|
+
langchain_agentx_python-2.2.3.dist-info/WHEEL,sha256=51RkbunBAw4BWsgaQWTpPhg4Diwp3c9P5iaLk67Hdtg,92
|
|
766
|
+
langchain_agentx_python-2.2.3.dist-info/top_level.txt,sha256=Ge284pniNt8xea0OLk2o9o32GqVpDhOYk20fwE-0xxA,17
|
|
767
|
+
langchain_agentx_python-2.2.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{langchain_agentx_python-2.2.1.dist-info → langchain_agentx_python-2.2.3.dist-info}/top_level.txt
RENAMED
|
File without changes
|