langchain-agentx-python 2.3.3__py3-none-any.whl → 2.3.4__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/loop/config/compaction_config.py +38 -0
- langchain_agentx/loop/config/loop_config.py +1 -0
- langchain_agentx/loop/context/pipeline.py +25 -7
- langchain_agentx/loop/context/settings.py +11 -0
- langchain_agentx/loop/context/stages/autocompact.py +51 -9
- langchain_agentx/loop/context/types.py +4 -0
- langchain_agentx/loop/exit/exit_logic.py +2 -0
- langchain_agentx/loop/graph/factory.py +145 -47
- langchain_agentx/observability/events/agent_event_projector.py +11 -0
- {langchain_agentx_python-2.3.3.dist-info → langchain_agentx_python-2.3.4.dist-info}/METADATA +1 -1
- {langchain_agentx_python-2.3.3.dist-info → langchain_agentx_python-2.3.4.dist-info}/RECORD +15 -14
- {langchain_agentx_python-2.3.3.dist-info → langchain_agentx_python-2.3.4.dist-info}/LICENSE +0 -0
- {langchain_agentx_python-2.3.3.dist-info → langchain_agentx_python-2.3.4.dist-info}/WHEEL +0 -0
- {langchain_agentx_python-2.3.3.dist-info → langchain_agentx_python-2.3.4.dist-info}/top_level.txt +0 -0
langchain_agentx/__init__.py
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Compaction 控制面 env 解析(对齐 CC DISABLE_COMPACT / DISABLE_AUTO_COMPACT)。"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _parse_bool_env(name: str) -> bool | None:
|
|
9
|
+
raw = os.environ.get(name, "").strip().lower()
|
|
10
|
+
if not raw:
|
|
11
|
+
return None
|
|
12
|
+
return raw in ("1", "true", "yes", "on")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def resolve_is_auto_compact_enabled(*, config_is_auto_compact: bool = True) -> bool:
|
|
16
|
+
"""CC:DISABLE_COMPACT 关全部;DISABLE_AUTO_COMPACT 仅关 proactive autocompact。"""
|
|
17
|
+
if _parse_bool_env("DISABLE_COMPACT") is True:
|
|
18
|
+
return False
|
|
19
|
+
if _parse_bool_env("DISABLE_AUTO_COMPACT") is True:
|
|
20
|
+
return False
|
|
21
|
+
return config_is_auto_compact
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def compute_autocompact_trigger_token_threshold(
|
|
25
|
+
*,
|
|
26
|
+
context_window_tokens: int,
|
|
27
|
+
max_output_tokens_reserved: int,
|
|
28
|
+
compact_buffer_tokens: int,
|
|
29
|
+
) -> int:
|
|
30
|
+
"""对齐 CC:effectiveWindow - AUTOCOMPACT_BUFFER_TOKENS。"""
|
|
31
|
+
effective = max(0, int(context_window_tokens) - int(max_output_tokens_reserved))
|
|
32
|
+
return max(0, effective - int(compact_buffer_tokens))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
__all__ = [
|
|
36
|
+
"compute_autocompact_trigger_token_threshold",
|
|
37
|
+
"resolve_is_auto_compact_enabled",
|
|
38
|
+
]
|
|
@@ -253,6 +253,7 @@ class AgentLoopConfig:
|
|
|
253
253
|
token_budget_max_continuations: int = 3
|
|
254
254
|
compact_buffer_tokens: int = 13_000
|
|
255
255
|
max_output_tokens_reserved: int = 20_000
|
|
256
|
+
is_auto_compact: bool = True
|
|
256
257
|
|
|
257
258
|
# -----------------------------------------------------------------------
|
|
258
259
|
# 运行模式
|
|
@@ -33,17 +33,33 @@ from .stages.base import CompactionStage
|
|
|
33
33
|
from .types import CompactProgress, ContextCompactionContext
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
def _apply_autocompact_failure_patch(
|
|
37
|
+
state: dict[str, Any],
|
|
38
|
+
stages_meta: list[dict[str, Any]],
|
|
39
|
+
patch: dict[str, Any],
|
|
40
|
+
) -> None:
|
|
41
|
+
ac = next((m for m in stages_meta if m.get("name") == "autocompact"), None)
|
|
42
|
+
if ac is None:
|
|
43
|
+
return
|
|
44
|
+
extra = ac.get("extra") or {}
|
|
45
|
+
prev = int(state.get("consecutive_autocompact_failures") or 0)
|
|
46
|
+
if extra.get("autocompact_llm_failed"):
|
|
47
|
+
patch["consecutive_autocompact_failures"] = prev + 1
|
|
48
|
+
elif extra.get("autocompact_mode") == "llm":
|
|
49
|
+
patch["consecutive_autocompact_failures"] = 0
|
|
50
|
+
|
|
51
|
+
|
|
36
52
|
class DefaultCompactionStages:
|
|
37
53
|
"""CC 五段默认装配(顺序即契约)。"""
|
|
38
54
|
|
|
39
55
|
@staticmethod
|
|
40
|
-
def build() -> tuple[CompactionStage, ...]:
|
|
56
|
+
def build(settings: CompactionSettings | None = None) -> tuple[CompactionStage, ...]:
|
|
41
57
|
return (
|
|
42
|
-
ToolResultBudgetStage(),
|
|
43
|
-
SnipCompactStage(),
|
|
44
|
-
MicrocompactStage(),
|
|
45
|
-
ContextCollapseStage(),
|
|
46
|
-
AutocompactStage(),
|
|
58
|
+
ToolResultBudgetStage(settings),
|
|
59
|
+
SnipCompactStage(settings),
|
|
60
|
+
MicrocompactStage(settings),
|
|
61
|
+
ContextCollapseStage(settings),
|
|
62
|
+
AutocompactStage(settings),
|
|
47
63
|
)
|
|
48
64
|
|
|
49
65
|
|
|
@@ -65,7 +81,7 @@ class ContextPipeline:
|
|
|
65
81
|
settings: CompactionSettings | None = None,
|
|
66
82
|
) -> ContextPipeline:
|
|
67
83
|
"""使用 `DefaultCompactionStages` 构建管道。"""
|
|
68
|
-
return cls(DefaultCompactionStages.build(), settings=settings)
|
|
84
|
+
return cls(DefaultCompactionStages.build(settings), settings=settings)
|
|
69
85
|
|
|
70
86
|
@property
|
|
71
87
|
def stages(self) -> tuple[CompactionStage, ...]:
|
|
@@ -117,6 +133,7 @@ class ContextPipeline:
|
|
|
117
133
|
"mode": ctx.mode,
|
|
118
134
|
}
|
|
119
135
|
|
|
136
|
+
_apply_autocompact_failure_patch(state, stages_meta, patch)
|
|
120
137
|
if not patch:
|
|
121
138
|
return {}
|
|
122
139
|
return patch
|
|
@@ -198,6 +215,7 @@ class ContextPipeline:
|
|
|
198
215
|
"mode": ctx.mode,
|
|
199
216
|
}
|
|
200
217
|
|
|
218
|
+
_apply_autocompact_failure_patch(state, stages_meta, patch)
|
|
201
219
|
if not patch:
|
|
202
220
|
return {}
|
|
203
221
|
return patch
|
|
@@ -32,6 +32,8 @@ class CompactionSettings:
|
|
|
32
32
|
prune_protected_tools: FrozenSet[str] = field(default_factory=lambda: frozenset({"Skill"}))
|
|
33
33
|
default_max_context_tokens: int = 120_000
|
|
34
34
|
default_compress_trigger_fraction: float = 0.8
|
|
35
|
+
# 非 None 时 AutocompactStage 用绝对触发线(由 AgentLoopConfig compact_buffer 派生)。
|
|
36
|
+
autocompact_trigger_token_threshold: int | None = None
|
|
35
37
|
default_compress_keep_recent_messages: int = 8
|
|
36
38
|
# --- autocompact LLM 提示词(对齐 `compact.ts` + `prompt.ts`)---
|
|
37
39
|
# 摘要插在保留 tail 之前 → 默认 `partial_up_to`;全量折叠无尾窗时用 `full`;与 CC partial pivot「from」一致时用 `partial_from`。
|
|
@@ -62,6 +64,8 @@ class CompactionSettings:
|
|
|
62
64
|
default_factory=QuerySourcePolicy.autocompact_skip_sources
|
|
63
65
|
)
|
|
64
66
|
autocompact_use_llm_when_available: bool = True
|
|
67
|
+
is_auto_compact_enabled: bool = True
|
|
68
|
+
max_consecutive_autocompact_failures: int = 3
|
|
65
69
|
autocompact_llm_excerpt_chars_per_message: int = 20_000
|
|
66
70
|
# --- snip carry → autocompact 阈值放宽(对齐 CC snipTokensFreed 计入阈值)---
|
|
67
71
|
# True:将本流水线已累计的 `snip_tokens_freed_carry` 加到触发阈值上,避免 snip 已释放后仍立刻 autocompact。
|
|
@@ -89,6 +93,12 @@ class CompactionSettings:
|
|
|
89
93
|
active_compaction_settings: CompactionSettings = CompactionSettings()
|
|
90
94
|
|
|
91
95
|
|
|
96
|
+
def autocompact_trigger_threshold_tokens(settings: CompactionSettings) -> int:
|
|
97
|
+
if settings.autocompact_trigger_token_threshold is not None:
|
|
98
|
+
return settings.autocompact_trigger_token_threshold
|
|
99
|
+
return int(settings.default_max_context_tokens * settings.default_compress_trigger_fraction)
|
|
100
|
+
|
|
101
|
+
|
|
92
102
|
def get_active_compaction_settings() -> CompactionSettings:
|
|
93
103
|
"""返回当前生效的策略(默认即模块级 `active_compaction_settings`)。"""
|
|
94
104
|
return active_compaction_settings
|
|
@@ -104,6 +114,7 @@ __all__ = [
|
|
|
104
114
|
"AutocompactLlmPromptKind",
|
|
105
115
|
"CompactionSettings",
|
|
106
116
|
"active_compaction_settings",
|
|
117
|
+
"autocompact_trigger_threshold_tokens",
|
|
107
118
|
"get_active_compaction_settings",
|
|
108
119
|
"set_active_compaction_settings",
|
|
109
120
|
]
|
|
@@ -25,7 +25,11 @@ from langchain_core.messages import HumanMessage, SystemMessage
|
|
|
25
25
|
from ..blocking_guard import CompactionBlockingGuard
|
|
26
26
|
from ..message_utils import stringify_content, total_estimated_tokens_for_messages
|
|
27
27
|
from ...prompt.compact import build_autocompact_llm_instruction_prompt, get_compact_user_summary_message
|
|
28
|
-
from ..settings import
|
|
28
|
+
from ..settings import (
|
|
29
|
+
CompactionSettings,
|
|
30
|
+
autocompact_trigger_threshold_tokens,
|
|
31
|
+
get_active_compaction_settings,
|
|
32
|
+
)
|
|
29
33
|
from ..types import CompactProgress, ContextCompactionContext, StageResult
|
|
30
34
|
from .base import CompactionStage
|
|
31
35
|
|
|
@@ -45,10 +49,25 @@ class AutocompactStage(CompactionStage):
|
|
|
45
49
|
|
|
46
50
|
def run(self, messages: list[Any], ctx: ContextCompactionContext) -> StageResult:
|
|
47
51
|
s = self._effective_settings()
|
|
52
|
+
if not s.is_auto_compact_enabled:
|
|
53
|
+
return StageResult(
|
|
54
|
+
messages=messages,
|
|
55
|
+
tokens_freed=0,
|
|
56
|
+
extra={"autocompact_skipped": "auto_compact_disabled"},
|
|
57
|
+
)
|
|
58
|
+
if ctx.consecutive_autocompact_failures >= s.max_consecutive_autocompact_failures:
|
|
59
|
+
return StageResult(
|
|
60
|
+
messages=messages,
|
|
61
|
+
tokens_freed=0,
|
|
62
|
+
extra={
|
|
63
|
+
"autocompact_skipped": "consecutive_failures",
|
|
64
|
+
"consecutive_autocompact_failures": ctx.consecutive_autocompact_failures,
|
|
65
|
+
},
|
|
66
|
+
)
|
|
48
67
|
if ctx.query_source in s.autocompact_skip_query_sources:
|
|
49
68
|
return StageResult(messages=messages, tokens_freed=0, extra={"autocompact_skipped": "query_source"})
|
|
50
69
|
total = total_estimated_tokens_for_messages(messages, s.num_chars_per_token)
|
|
51
|
-
threshold =
|
|
70
|
+
threshold = autocompact_trigger_threshold_tokens(s)
|
|
52
71
|
slack = ctx.snip_tokens_freed_carry if s.autocompact_snip_carry_threshold_slack else 0
|
|
53
72
|
if total <= threshold + slack:
|
|
54
73
|
return StageResult(messages=messages, tokens_freed=0)
|
|
@@ -66,11 +85,12 @@ class AutocompactStage(CompactionStage):
|
|
|
66
85
|
tail = rest[-k:]
|
|
67
86
|
|
|
68
87
|
block_llm = CompactionBlockingGuard(settings=s).should_block_compact_llm(messages)
|
|
69
|
-
|
|
88
|
+
attempted_llm = (
|
|
70
89
|
s.autocompact_use_llm_when_available
|
|
71
90
|
and ctx.model is not None
|
|
72
91
|
and not block_llm
|
|
73
|
-
)
|
|
92
|
+
)
|
|
93
|
+
if attempted_llm:
|
|
74
94
|
summary = _invoke_summary(ctx.model, s, head)
|
|
75
95
|
if summary:
|
|
76
96
|
# 修复后:不包含 leading,state 不含 SystemMessage
|
|
@@ -104,20 +124,38 @@ class AutocompactStage(CompactionStage):
|
|
|
104
124
|
] + tail
|
|
105
125
|
new_total = total_estimated_tokens_for_messages(folded, s.num_chars_per_token)
|
|
106
126
|
mode = "prune_blocked_llm" if block_llm else "prune"
|
|
127
|
+
extra: dict[str, Any] = {"autocompact_mode": mode, "folded_messages": len(head)}
|
|
128
|
+
if attempted_llm:
|
|
129
|
+
extra["autocompact_llm_failed"] = True
|
|
107
130
|
return StageResult(
|
|
108
131
|
messages=folded,
|
|
109
132
|
tokens_freed=max(0, total - new_total),
|
|
110
|
-
extra=
|
|
133
|
+
extra=extra,
|
|
111
134
|
)
|
|
112
135
|
|
|
113
136
|
async def arun(self, messages: list[Any], ctx: ContextCompactionContext) -> StageResult:
|
|
114
137
|
"""Async 版本:LLM 摘要使用 astream 流式生成,支持进度回调。"""
|
|
115
138
|
s = self._effective_settings()
|
|
139
|
+
if not s.is_auto_compact_enabled:
|
|
140
|
+
return StageResult(
|
|
141
|
+
messages=messages,
|
|
142
|
+
tokens_freed=0,
|
|
143
|
+
extra={"autocompact_skipped": "auto_compact_disabled"},
|
|
144
|
+
)
|
|
145
|
+
if ctx.consecutive_autocompact_failures >= s.max_consecutive_autocompact_failures:
|
|
146
|
+
return StageResult(
|
|
147
|
+
messages=messages,
|
|
148
|
+
tokens_freed=0,
|
|
149
|
+
extra={
|
|
150
|
+
"autocompact_skipped": "consecutive_failures",
|
|
151
|
+
"consecutive_autocompact_failures": ctx.consecutive_autocompact_failures,
|
|
152
|
+
},
|
|
153
|
+
)
|
|
116
154
|
if ctx.query_source in s.autocompact_skip_query_sources:
|
|
117
155
|
return StageResult(messages=messages, tokens_freed=0, extra={"autocompact_skipped": "query_source"})
|
|
118
156
|
|
|
119
157
|
total = total_estimated_tokens_for_messages(messages, s.num_chars_per_token)
|
|
120
|
-
threshold =
|
|
158
|
+
threshold = autocompact_trigger_threshold_tokens(s)
|
|
121
159
|
slack = ctx.snip_tokens_freed_carry if s.autocompact_snip_carry_threshold_slack else 0
|
|
122
160
|
if total <= threshold + slack:
|
|
123
161
|
return StageResult(messages=messages, tokens_freed=0)
|
|
@@ -135,11 +173,12 @@ class AutocompactStage(CompactionStage):
|
|
|
135
173
|
tail = rest[-k:]
|
|
136
174
|
|
|
137
175
|
block_llm = CompactionBlockingGuard(settings=s).should_block_compact_llm(messages)
|
|
138
|
-
|
|
176
|
+
attempted_llm = (
|
|
139
177
|
s.autocompact_use_llm_when_available
|
|
140
178
|
and ctx.model is not None
|
|
141
179
|
and not block_llm
|
|
142
|
-
)
|
|
180
|
+
)
|
|
181
|
+
if attempted_llm:
|
|
143
182
|
summary = await _astream_summary(ctx.model, s, head, ctx.progress_callback)
|
|
144
183
|
if summary:
|
|
145
184
|
folded = [
|
|
@@ -172,10 +211,13 @@ class AutocompactStage(CompactionStage):
|
|
|
172
211
|
] + tail
|
|
173
212
|
new_total = total_estimated_tokens_for_messages(folded, s.num_chars_per_token)
|
|
174
213
|
mode = "prune_blocked_llm" if block_llm else "prune"
|
|
214
|
+
extra: dict[str, Any] = {"autocompact_mode": mode, "folded_messages": len(head)}
|
|
215
|
+
if attempted_llm:
|
|
216
|
+
extra["autocompact_llm_failed"] = True
|
|
175
217
|
return StageResult(
|
|
176
218
|
messages=folded,
|
|
177
219
|
tokens_freed=max(0, total - new_total),
|
|
178
|
-
extra=
|
|
220
|
+
extra=extra,
|
|
179
221
|
)
|
|
180
222
|
|
|
181
223
|
|
|
@@ -38,6 +38,7 @@ class ContextCompactionContext:
|
|
|
38
38
|
model: Any | None = None
|
|
39
39
|
snip_tokens_freed_carry: int = 0
|
|
40
40
|
query_source: str | None = None
|
|
41
|
+
consecutive_autocompact_failures: int = 0
|
|
41
42
|
config: CompactionConfig = field(default_factory=CompactionConfig)
|
|
42
43
|
progress_callback: CompactProgressCallback = None
|
|
43
44
|
mode: str = "proactive"
|
|
@@ -47,11 +48,14 @@ class ContextCompactionContext:
|
|
|
47
48
|
def from_state(
|
|
48
49
|
cls, state: Mapping[str, Any], model: Any | None, mode: str = "proactive"
|
|
49
50
|
) -> ContextCompactionContext:
|
|
51
|
+
raw_failures = state.get("consecutive_autocompact_failures")
|
|
52
|
+
failures = int(raw_failures) if isinstance(raw_failures, int) else 0
|
|
50
53
|
return cls(
|
|
51
54
|
model=model,
|
|
52
55
|
query_source=state.get("query_source")
|
|
53
56
|
if isinstance(state.get("query_source"), str)
|
|
54
57
|
else None,
|
|
58
|
+
consecutive_autocompact_failures=max(0, failures),
|
|
55
59
|
mode=mode,
|
|
56
60
|
)
|
|
57
61
|
|
|
@@ -204,6 +204,7 @@ def create_initial_state(
|
|
|
204
204
|
# 恢复路径守卫状态
|
|
205
205
|
"collapse_retry_available": False,
|
|
206
206
|
"has_attempted_reactive_compact": False,
|
|
207
|
+
"consecutive_autocompact_failures": 0,
|
|
207
208
|
"compaction_pipeline_meta": None,
|
|
208
209
|
"max_output_tokens_override": None,
|
|
209
210
|
"max_output_tokens_recovery_count": 0,
|
|
@@ -248,6 +249,7 @@ class AgentLoopState(TypedDict):
|
|
|
248
249
|
withhold_retry_count: int # withhold 已重试次数
|
|
249
250
|
collapse_retry_available: bool # collapse_drain_retry 相关守卫
|
|
250
251
|
has_attempted_reactive_compact: bool # reactive_compact 重试守卫
|
|
252
|
+
consecutive_autocompact_failures: int # proactive autocompact LLM 连续失败(CC 熔断)
|
|
251
253
|
compaction_pipeline_meta: dict[str, Any] | None # prune_and_compress 观测
|
|
252
254
|
max_output_tokens_override: int | None # max_output_tokens 升档参数
|
|
253
255
|
max_output_tokens_recovery_count: int # max_output_tokens 恢复计数
|
|
@@ -10,20 +10,15 @@ LangChain AgentX Agent Factory
|
|
|
10
10
|
|
|
11
11
|
参考设计文档:.claude/design/create-opencode-style-agent-design.md
|
|
12
12
|
|
|
13
|
-
LangChain AgentX Agent 状态图(文字版,含 loop_controller):
|
|
13
|
+
LangChain AgentX Agent 状态图(文字版,含 loop_controller · proactive compact gate):
|
|
14
14
|
|
|
15
|
-
START
|
|
15
|
+
START → hook_loop_start → prune_and_compress → hook_before_model → model
|
|
16
16
|
↓
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
↓
|
|
23
|
-
loop_controller(集中处理 resolution / terminal / 工具调用)
|
|
24
|
-
├─ resolution.kind=terminal → END(或 task reconcile / recovery 分支)
|
|
25
|
-
├─ 有工具调用 → tools → (task_event_*/prune_and_compress) → model
|
|
26
|
-
└─ 无工具调用 → END
|
|
17
|
+
hook_stop → loop_controller
|
|
18
|
+
├─ terminal → hook_loop_end → END
|
|
19
|
+
├─ tools → (task_event_* →) prune_and_compress → hook_before_model → model
|
|
20
|
+
├─ 再进 model(无 tools)→ prune_and_compress → hook_before_model → model
|
|
21
|
+
└─ reactive_compact → prune_and_compress(或 task 链)→ … → model
|
|
27
22
|
"""
|
|
28
23
|
|
|
29
24
|
from __future__ import annotations
|
|
@@ -39,6 +34,16 @@ from langchain_core.messages import HumanMessage, SystemMessage
|
|
|
39
34
|
from langchain_core.runnables import RunnableConfig
|
|
40
35
|
from langgraph._internal._runnable import RunnableCallable
|
|
41
36
|
from langgraph.constants import END, START
|
|
37
|
+
|
|
38
|
+
_PRE_MODEL_COMPACT_NODE = "prune_and_compress"
|
|
39
|
+
_BEFORE_MODEL_NODE = "hook_before_model"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _pre_model_gate_destination(loop_entry_node: str) -> str:
|
|
43
|
+
"""CC 对齐:直连 hook_before_model 的 loop 续跑须先过 proactive compact gate。"""
|
|
44
|
+
if loop_entry_node == _BEFORE_MODEL_NODE:
|
|
45
|
+
return _PRE_MODEL_COMPACT_NODE
|
|
46
|
+
return loop_entry_node
|
|
42
47
|
from langgraph.graph.state import StateGraph
|
|
43
48
|
import asyncio
|
|
44
49
|
import dataclasses
|
|
@@ -66,8 +71,9 @@ from ..model.schema_and_format import (
|
|
|
66
71
|
)
|
|
67
72
|
from ..model.model_node import ModelNode
|
|
68
73
|
from ..model.model_nodes import make_model_nodes
|
|
69
|
-
from ..context import default_loop_context_compaction
|
|
74
|
+
from ..context import LoopContextCompaction, default_loop_context_compaction
|
|
70
75
|
from ..context.settings import CompactionSettings
|
|
76
|
+
from ..context.types import CompactProgress
|
|
71
77
|
from ..injection.dedup import filter_attachment_dicts_by_task_command_id
|
|
72
78
|
from ..message_contract import to_record
|
|
73
79
|
from ..model.tool_call_degradation_corrector import (
|
|
@@ -102,6 +108,10 @@ from ...memory.memdir.paths import is_memory_enabled
|
|
|
102
108
|
from ..prompt import SystemPromptSection, build_effective_system_prompt
|
|
103
109
|
from ..prompt.session_context import get_default_session_context_sections
|
|
104
110
|
from ..config import ModelContextResolver
|
|
111
|
+
from ..config.compaction_config import (
|
|
112
|
+
compute_autocompact_trigger_token_threshold,
|
|
113
|
+
resolve_is_auto_compact_enabled,
|
|
114
|
+
)
|
|
105
115
|
from ..config.interaction_profile import (
|
|
106
116
|
assemble_services,
|
|
107
117
|
normalize_config,
|
|
@@ -556,7 +566,7 @@ class LoopGraphBuilder:
|
|
|
556
566
|
# 运行时需要的额外值存储在 self._* 字段中
|
|
557
567
|
|
|
558
568
|
self._compaction_settings = self._build_compaction_settings()
|
|
559
|
-
self._loop_context_compaction =
|
|
569
|
+
self._loop_context_compaction = LoopContextCompaction.with_default_pipeline(
|
|
560
570
|
settings=self._compaction_settings
|
|
561
571
|
)
|
|
562
572
|
self._model = model
|
|
@@ -1354,15 +1364,29 @@ class LoopGraphBuilder:
|
|
|
1354
1364
|
|
|
1355
1365
|
def _build_compaction_settings(self) -> CompactionSettings:
|
|
1356
1366
|
base = CompactionSettings()
|
|
1367
|
+
context_window = self._model_context_resolver.resolve_context_window(self._config)
|
|
1368
|
+
trigger_threshold = compute_autocompact_trigger_token_threshold(
|
|
1369
|
+
context_window_tokens=context_window,
|
|
1370
|
+
max_output_tokens_reserved=self._config.max_output_tokens_reserved,
|
|
1371
|
+
compact_buffer_tokens=self._config.compact_buffer_tokens,
|
|
1372
|
+
)
|
|
1373
|
+
auto_compact_enabled = resolve_is_auto_compact_enabled(
|
|
1374
|
+
config_is_auto_compact=self._config.is_auto_compact
|
|
1375
|
+
)
|
|
1376
|
+
# G1-A (CC 0331): auto + reactive 路径下不在 call 前 synthetic blocking_limit。
|
|
1377
|
+
enable_main_token_block = base.enable_main_model_context_token_block
|
|
1378
|
+
if auto_compact_enabled:
|
|
1379
|
+
enable_main_token_block = False
|
|
1357
1380
|
return CompactionSettings(
|
|
1358
1381
|
num_chars_per_token=base.num_chars_per_token,
|
|
1359
1382
|
prune_protect_tokens=base.prune_protect_tokens,
|
|
1360
1383
|
prune_minimum_tokens=base.prune_minimum_tokens,
|
|
1361
1384
|
prune_protected_tools=base.prune_protected_tools,
|
|
1362
|
-
default_max_context_tokens=
|
|
1363
|
-
self._config
|
|
1364
|
-
),
|
|
1385
|
+
default_max_context_tokens=context_window,
|
|
1365
1386
|
default_compress_trigger_fraction=base.default_compress_trigger_fraction,
|
|
1387
|
+
autocompact_trigger_token_threshold=trigger_threshold,
|
|
1388
|
+
is_auto_compact_enabled=auto_compact_enabled,
|
|
1389
|
+
max_consecutive_autocompact_failures=base.max_consecutive_autocompact_failures,
|
|
1366
1390
|
default_compress_keep_recent_messages=base.default_compress_keep_recent_messages,
|
|
1367
1391
|
autocompact_llm_prompt_kind=base.autocompact_llm_prompt_kind,
|
|
1368
1392
|
compact_custom_instructions=base.compact_custom_instructions,
|
|
@@ -1382,7 +1406,7 @@ class LoopGraphBuilder:
|
|
|
1382
1406
|
compaction_token_warn_fraction=base.compaction_token_warn_fraction,
|
|
1383
1407
|
compaction_block_compact_llm_fraction=base.compaction_block_compact_llm_fraction,
|
|
1384
1408
|
compaction_block_main_model_fraction=base.compaction_block_main_model_fraction,
|
|
1385
|
-
enable_main_model_context_token_block=
|
|
1409
|
+
enable_main_model_context_token_block=enable_main_token_block,
|
|
1386
1410
|
enable_tool_transcript_repair_before_llm=base.enable_tool_transcript_repair_before_llm,
|
|
1387
1411
|
emit_compaction_pipeline_meta=base.emit_compaction_pipeline_meta,
|
|
1388
1412
|
)
|
|
@@ -1426,19 +1450,21 @@ class LoopGraphBuilder:
|
|
|
1426
1450
|
context_schema=self._context_schema,
|
|
1427
1451
|
)
|
|
1428
1452
|
graph_inner.add_node("model", model_node)
|
|
1453
|
+
graph_inner.add_node(
|
|
1454
|
+
_PRE_MODEL_COMPACT_NODE,
|
|
1455
|
+
RunnableCallable(
|
|
1456
|
+
self._prune_and_compress_node,
|
|
1457
|
+
self._prune_and_compress_node_async,
|
|
1458
|
+
trace=False,
|
|
1459
|
+
),
|
|
1460
|
+
)
|
|
1429
1461
|
if tool_node is not None:
|
|
1430
1462
|
graph_inner.add_node("tools", tool_node)
|
|
1431
|
-
|
|
1432
|
-
graph_inner.add_node(
|
|
1433
|
-
"prune_and_compress",
|
|
1434
|
-
RunnableCallable(
|
|
1435
|
-
self._prune_and_compress_node,
|
|
1436
|
-
self._prune_and_compress_node_async,
|
|
1437
|
-
trace=False,
|
|
1438
|
-
),
|
|
1439
|
-
)
|
|
1440
1463
|
return graph_inner
|
|
1441
1464
|
|
|
1465
|
+
def _wire_prune_and_compress_to_before_model(self, graph_inner: Any) -> None:
|
|
1466
|
+
graph_inner.add_edge(_PRE_MODEL_COMPACT_NODE, _BEFORE_MODEL_NODE)
|
|
1467
|
+
|
|
1442
1468
|
def _prune_and_compress_node(self, state: dict[str, Any], runtime: Any) -> dict[str, Any]:
|
|
1443
1469
|
return self._run_prune_and_compress_with_trace(state)
|
|
1444
1470
|
|
|
@@ -1461,6 +1487,31 @@ class LoopGraphBuilder:
|
|
|
1461
1487
|
"skipping wait_for_extraction (use ainvoke for CC-aligned wait)"
|
|
1462
1488
|
)
|
|
1463
1489
|
|
|
1490
|
+
@staticmethod
|
|
1491
|
+
def _compact_progress_phase(
|
|
1492
|
+
progress: CompactProgress,
|
|
1493
|
+
*,
|
|
1494
|
+
seen: bool,
|
|
1495
|
+
) -> tuple[str, bool]:
|
|
1496
|
+
if not seen:
|
|
1497
|
+
return "start", True
|
|
1498
|
+
if progress.stage == "done" and progress.percent >= 100:
|
|
1499
|
+
return "end", True
|
|
1500
|
+
return "tick", True
|
|
1501
|
+
|
|
1502
|
+
def _merge_compact_progress_into_patch(
|
|
1503
|
+
self,
|
|
1504
|
+
patch: dict[str, Any],
|
|
1505
|
+
progress_events: list[dict[str, Any]],
|
|
1506
|
+
) -> None:
|
|
1507
|
+
if not progress_events:
|
|
1508
|
+
return
|
|
1509
|
+
meta = patch.get("compaction_pipeline_meta")
|
|
1510
|
+
if not isinstance(meta, dict):
|
|
1511
|
+
meta = {}
|
|
1512
|
+
patch["compaction_pipeline_meta"] = meta
|
|
1513
|
+
meta["compact_progress"] = progress_events
|
|
1514
|
+
|
|
1464
1515
|
def _apply_prune_and_compress(self, state: dict[str, Any]) -> dict[str, Any]:
|
|
1465
1516
|
if self._session_memory_compact_bridge is not None:
|
|
1466
1517
|
compacted_messages = self._session_memory_compact_bridge.try_compact(
|
|
@@ -1481,6 +1532,55 @@ class LoopGraphBuilder:
|
|
|
1481
1532
|
patch["collapse_retry_available"] = bool(compaction_meta.get("tokens_freed_sum", 0))
|
|
1482
1533
|
return patch
|
|
1483
1534
|
|
|
1535
|
+
async def _apply_prune_and_compress_async(self, state: dict[str, Any]) -> dict[str, Any]:
|
|
1536
|
+
if self._session_memory_compact_bridge is not None:
|
|
1537
|
+
compacted_messages = self._session_memory_compact_bridge.try_compact(
|
|
1538
|
+
list(state.get("messages") or [])
|
|
1539
|
+
)
|
|
1540
|
+
if compacted_messages is not None:
|
|
1541
|
+
return {
|
|
1542
|
+
"messages": compacted_messages,
|
|
1543
|
+
"collapse_retry_available": True,
|
|
1544
|
+
"compaction_pipeline_meta": {
|
|
1545
|
+
"autocompact_mode": "session_memory",
|
|
1546
|
+
"session_memory_compaction": "applied",
|
|
1547
|
+
},
|
|
1548
|
+
}
|
|
1549
|
+
progress_events: list[dict[str, Any]] = []
|
|
1550
|
+
seen_progress = False
|
|
1551
|
+
|
|
1552
|
+
def _on_progress(progress: CompactProgress) -> None:
|
|
1553
|
+
nonlocal seen_progress
|
|
1554
|
+
phase, seen_progress = self._compact_progress_phase(
|
|
1555
|
+
progress, seen=seen_progress
|
|
1556
|
+
)
|
|
1557
|
+
progress_events.append(
|
|
1558
|
+
{
|
|
1559
|
+
"phase": phase,
|
|
1560
|
+
"stage": progress.stage,
|
|
1561
|
+
"stage_index": progress.stage_index,
|
|
1562
|
+
"total_stages": progress.total_stages,
|
|
1563
|
+
"percent": progress.percent,
|
|
1564
|
+
"detail": progress.detail,
|
|
1565
|
+
}
|
|
1566
|
+
)
|
|
1567
|
+
|
|
1568
|
+
emit_progress = bool(
|
|
1569
|
+
self._compaction_settings.is_auto_compact_enabled
|
|
1570
|
+
and self._compaction_settings.emit_compaction_pipeline_meta
|
|
1571
|
+
)
|
|
1572
|
+
patch = await self._loop_context_compaction.arun(
|
|
1573
|
+
state,
|
|
1574
|
+
model=self._model,
|
|
1575
|
+
progress_callback=_on_progress if emit_progress else None,
|
|
1576
|
+
)
|
|
1577
|
+
if emit_progress:
|
|
1578
|
+
self._merge_compact_progress_into_patch(patch, progress_events)
|
|
1579
|
+
compaction_meta = patch.get("compaction_pipeline_meta")
|
|
1580
|
+
if isinstance(compaction_meta, dict):
|
|
1581
|
+
patch["collapse_retry_available"] = bool(compaction_meta.get("tokens_freed_sum", 0))
|
|
1582
|
+
return patch
|
|
1583
|
+
|
|
1484
1584
|
def _run_prune_and_compress_with_trace(self, state: dict[str, Any]) -> dict[str, Any]:
|
|
1485
1585
|
"""执行 compaction,并在当前 session 内记录 compaction span(sync 路径)。"""
|
|
1486
1586
|
collector = state.get("_trace_collector")
|
|
@@ -1546,7 +1646,7 @@ class LoopGraphBuilder:
|
|
|
1546
1646
|
try:
|
|
1547
1647
|
if self._session_memory_compact_bridge is not None:
|
|
1548
1648
|
await self._session_memory_compact_bridge.wait_for_extraction()
|
|
1549
|
-
patch = self.
|
|
1649
|
+
patch = await self._apply_prune_and_compress_async(state)
|
|
1550
1650
|
except Exception as exc:
|
|
1551
1651
|
if span_id is not None:
|
|
1552
1652
|
collector.span_end(
|
|
@@ -1593,6 +1693,7 @@ class LoopGraphBuilder:
|
|
|
1593
1693
|
skill_prefetch_provider=skill_prefetch_provider,
|
|
1594
1694
|
entry_node=entry_node,
|
|
1595
1695
|
)
|
|
1696
|
+
self._wire_prune_and_compress_to_before_model(graph_inner)
|
|
1596
1697
|
graph_inner.add_edge("hook_before_model", "model")
|
|
1597
1698
|
return {
|
|
1598
1699
|
"entry_node": entry_node,
|
|
@@ -1896,12 +1997,8 @@ class LoopGraphBuilder:
|
|
|
1896
1997
|
RunnableCallable(_task_event_reserve_node, None, trace=False),
|
|
1897
1998
|
)
|
|
1898
1999
|
graph_inner.add_edge("task_event_commit_ack", "task_event_reserve")
|
|
1899
|
-
# Phase 5A
|
|
1900
|
-
|
|
1901
|
-
graph_inner.add_edge("task_event_reserve", "prune_and_compress")
|
|
1902
|
-
graph_inner.add_edge("prune_and_compress", raw_loop_entry_node)
|
|
1903
|
-
else:
|
|
1904
|
-
graph_inner.add_edge("task_event_reserve", raw_loop_entry_node)
|
|
2000
|
+
# Phase 5A / proactive autocompact:task 注入后再压缩,再进 hook_before_model。
|
|
2001
|
+
graph_inner.add_edge("task_event_reserve", _PRE_MODEL_COMPACT_NODE)
|
|
1905
2002
|
return "task_event_commit_ack"
|
|
1906
2003
|
|
|
1907
2004
|
def _find_skill_prefetch_provider(
|
|
@@ -1984,10 +2081,10 @@ class LoopGraphBuilder:
|
|
|
1984
2081
|
)
|
|
1985
2082
|
graph_inner.add_edge(START, "skill_init")
|
|
1986
2083
|
graph_inner.add_edge("skill_init", "hook_loop_start")
|
|
1987
|
-
graph_inner.add_edge("hook_loop_start",
|
|
2084
|
+
graph_inner.add_edge("hook_loop_start", _PRE_MODEL_COMPACT_NODE)
|
|
1988
2085
|
return
|
|
1989
2086
|
graph_inner.add_edge(START, "hook_loop_start")
|
|
1990
|
-
graph_inner.add_edge("hook_loop_start",
|
|
2087
|
+
graph_inner.add_edge("hook_loop_start", _PRE_MODEL_COMPACT_NODE)
|
|
1991
2088
|
|
|
1992
2089
|
def _wire_main_edges(self, *, graph_inner: Any, tool_node: Any, routing: dict[str, Any]) -> None:
|
|
1993
2090
|
loop_entry_node = routing["loop_entry_node"]
|
|
@@ -2040,8 +2137,8 @@ class LoopGraphBuilder:
|
|
|
2040
2137
|
tools_model_destination = loop_entry_node
|
|
2041
2138
|
tools_to_model_destinations = [loop_entry_node, exit_node]
|
|
2042
2139
|
else:
|
|
2043
|
-
tools_model_destination =
|
|
2044
|
-
tools_to_model_destinations = [
|
|
2140
|
+
tools_model_destination = _PRE_MODEL_COMPACT_NODE
|
|
2141
|
+
tools_to_model_destinations = [_PRE_MODEL_COMPACT_NODE, exit_node]
|
|
2045
2142
|
|
|
2046
2143
|
graph_inner.add_conditional_edges(
|
|
2047
2144
|
"tools",
|
|
@@ -2056,8 +2153,6 @@ class LoopGraphBuilder:
|
|
|
2056
2153
|
),
|
|
2057
2154
|
tools_to_model_destinations,
|
|
2058
2155
|
)
|
|
2059
|
-
if not wire_task_event_nodes:
|
|
2060
|
-
graph_inner.add_edge("prune_and_compress", loop_entry_node)
|
|
2061
2156
|
graph_inner.add_edge(loop_exit_node, "hook_after_model")
|
|
2062
2157
|
graph_inner.add_edge("hook_after_model", "hook_stop")
|
|
2063
2158
|
self._wire_loop_controller(
|
|
@@ -2079,11 +2174,12 @@ class LoopGraphBuilder:
|
|
|
2079
2174
|
wire_task_event_nodes: bool,
|
|
2080
2175
|
tools_destination: str | None = None,
|
|
2081
2176
|
) -> None:
|
|
2177
|
+
model_gate = _pre_model_gate_destination(loop_entry_node)
|
|
2082
2178
|
graph_inner.add_node(
|
|
2083
2179
|
"loop_controller",
|
|
2084
2180
|
RunnableCallable(
|
|
2085
2181
|
_make_loop_controller_node(
|
|
2086
|
-
model_destination=
|
|
2182
|
+
model_destination=model_gate,
|
|
2087
2183
|
tools_destination=tools_destination or loop_entry_node,
|
|
2088
2184
|
structured_output_tools=self._structured_output_tools,
|
|
2089
2185
|
end_destination=exit_node,
|
|
@@ -2107,7 +2203,7 @@ class LoopGraphBuilder:
|
|
|
2107
2203
|
def _reactive_compact_node(state, runtime):
|
|
2108
2204
|
node = ReactiveCompactNode(
|
|
2109
2205
|
compaction_service=default_loop_context_compaction(),
|
|
2110
|
-
loop_entry_destination=
|
|
2206
|
+
loop_entry_destination=model_gate,
|
|
2111
2207
|
end_destination=exit_node,
|
|
2112
2208
|
)
|
|
2113
2209
|
return node(state)
|
|
@@ -2116,13 +2212,14 @@ class LoopGraphBuilder:
|
|
|
2116
2212
|
"reactive_compact",
|
|
2117
2213
|
RunnableCallable(_reactive_compact_node, None, trace=False),
|
|
2118
2214
|
)
|
|
2215
|
+
reactive_destinations = [model_gate, exit_node]
|
|
2119
2216
|
graph_inner.add_conditional_edges(
|
|
2120
2217
|
"reactive_compact",
|
|
2121
|
-
lambda state: state.get("destination",
|
|
2122
|
-
|
|
2218
|
+
lambda state: state.get("destination", model_gate),
|
|
2219
|
+
reactive_destinations,
|
|
2123
2220
|
)
|
|
2124
2221
|
|
|
2125
|
-
loop_controller_destinations = [
|
|
2222
|
+
loop_controller_destinations = [model_gate, exit_node, "reactive_compact"]
|
|
2126
2223
|
if tools_destination is not None:
|
|
2127
2224
|
loop_controller_destinations.insert(0, tools_destination)
|
|
2128
2225
|
if wire_task_event_nodes and "task_event_commit_ack" not in loop_controller_destinations:
|
|
@@ -2144,16 +2241,17 @@ class LoopGraphBuilder:
|
|
|
2144
2241
|
wire_task_event_nodes: bool,
|
|
2145
2242
|
) -> None:
|
|
2146
2243
|
graph_inner.add_edge(loop_exit_node, "hook_after_model")
|
|
2244
|
+
model_gate = _pre_model_gate_destination(loop_entry_node)
|
|
2147
2245
|
graph_inner.add_conditional_edges(
|
|
2148
2246
|
"hook_after_model",
|
|
2149
2247
|
RunnableCallable(
|
|
2150
2248
|
_make_model_to_model_edge(
|
|
2151
|
-
model_destination=
|
|
2249
|
+
model_destination=model_gate,
|
|
2152
2250
|
end_destination="hook_stop",
|
|
2153
2251
|
),
|
|
2154
2252
|
trace=False,
|
|
2155
2253
|
),
|
|
2156
|
-
[
|
|
2254
|
+
[model_gate, "hook_stop"],
|
|
2157
2255
|
)
|
|
2158
2256
|
self._wire_loop_controller(
|
|
2159
2257
|
graph_inner=graph_inner,
|
|
@@ -128,6 +128,7 @@ class LangchainAgentEventType(Enum):
|
|
|
128
128
|
HOOK_PROGRESS = "hook-progress"
|
|
129
129
|
HOOK_FINISHED = "hook-finished"
|
|
130
130
|
COMPACT_BOUNDARY = "compact-boundary"
|
|
131
|
+
COMPACT_PROGRESS = "compact-progress"
|
|
131
132
|
MEMORY_SAVED = "memory-saved"
|
|
132
133
|
SUBAGENT_START = "subagent-start"
|
|
133
134
|
SUBAGENT_END = "subagent-end"
|
|
@@ -850,6 +851,16 @@ class AgentEventProjector:
|
|
|
850
851
|
|
|
851
852
|
if self._is_compact_node(name):
|
|
852
853
|
meta = extract_compaction_meta_from_chain_end_data(data)
|
|
854
|
+
if isinstance(meta, dict) and self.enable_compact_events:
|
|
855
|
+
raw_progress = meta.get("compact_progress")
|
|
856
|
+
if isinstance(raw_progress, list):
|
|
857
|
+
for item in raw_progress:
|
|
858
|
+
if isinstance(item, dict):
|
|
859
|
+
yield self._event(
|
|
860
|
+
event_type=LangchainAgentEventType.COMPACT_PROGRESS,
|
|
861
|
+
data=dict(item),
|
|
862
|
+
step_index=self.state.step_index or None,
|
|
863
|
+
)
|
|
853
864
|
if is_user_visible_compact(meta):
|
|
854
865
|
if self.enable_compact_events:
|
|
855
866
|
compact_data = self._extract_compact_summary(data)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
langchain_agentx/__init__.py,sha256=
|
|
1
|
+
langchain_agentx/__init__.py,sha256=t5u-2g4slzGHVtYyJTJcFQgv_d5BfqHyJWeSDe9FMHY,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
|
|
@@ -31,8 +31,9 @@ langchain_agentx/loop/message_contract.py,sha256=Twl83TneU2PRdxgGRBxs6S9_ovRT6cb
|
|
|
31
31
|
langchain_agentx/loop/run_context.py,sha256=dhNiLhvqD_QYacGMA0B5P3wWpSe3O6wU_XcVEzb86Z4,8303
|
|
32
32
|
langchain_agentx/loop/config/__init__.py,sha256=0pf3Mml7LZpQ1C3_AtROFQClrBQegaGCG4YCTfSr9v8,1137
|
|
33
33
|
langchain_agentx/loop/config/agent_config.py,sha256=tOnAHFor6dkle3FvUOVx0YsmiYVTH11UrWSyTmOLV0c,3100
|
|
34
|
+
langchain_agentx/loop/config/compaction_config.py,sha256=MmXqY47-9nPDhdXvnU92Xp0XeaZ605ErQwX9d2emEkM,1176
|
|
34
35
|
langchain_agentx/loop/config/interaction_profile.py,sha256=UWrlI3aTWjYRq1mDeXL-xL-iCrQU-bXDXhETP6q9icY,10020
|
|
35
|
-
langchain_agentx/loop/config/loop_config.py,sha256=
|
|
36
|
+
langchain_agentx/loop/config/loop_config.py,sha256=3kYDXg91PSDNVUdHGm6In0mHJRpfrkITs4OLKdOngYY,16180
|
|
36
37
|
langchain_agentx/loop/config/loop_runtime_overlay.py,sha256=PuB4vFdqCHXRbAFhAJIrtwq9pUIrHafyn0ApD4s06KU,2440
|
|
37
38
|
langchain_agentx/loop/config/model_context_resolver.py,sha256=o9RR0Vnu07TD4Y3V8jk5V1NfkMcPcLjE8uaaLOe22Qo,4067
|
|
38
39
|
langchain_agentx/loop/config/model_retry_config.py,sha256=bakCbGeNRO-_SXMT_LLE3nu3m9scZe1MSxPdyEGO99w,8178
|
|
@@ -45,13 +46,13 @@ langchain_agentx/loop/context/__init__.py,sha256=RXVTFjHcH6_8q1x13Qk9ZP8RVbqZoyh
|
|
|
45
46
|
langchain_agentx/loop/context/blocking_guard.py,sha256=Rmt5qZdE8Zf0bt-Q6WwMSfG869772PE8w1mNPvBQRCQ,3789
|
|
46
47
|
langchain_agentx/loop/context/compaction_service.py,sha256=MwAPPaT31XbzgwqpuknGBZlYBRKxwyhWXDifEnBgh2E,3725
|
|
47
48
|
langchain_agentx/loop/context/message_utils.py,sha256=6qIwtHeh63OlMqOnPUpEEWRknU9KJTGkcY1v3tz6feY,2010
|
|
48
|
-
langchain_agentx/loop/context/pipeline.py,sha256=
|
|
49
|
+
langchain_agentx/loop/context/pipeline.py,sha256=PrhCWWKUGGwMGd-F8UX6vt3U7tlZo2ZZDLV0CTTDSJ4,8279
|
|
49
50
|
langchain_agentx/loop/context/query_source.py,sha256=-wqVpST64jXF1ZelcGdvIsJE4ngv54eco4gmeS3pyyg,5118
|
|
50
51
|
langchain_agentx/loop/context/recovery_mode.py,sha256=ytHGnE-g91pDQIkyVcfxEw6XgJGZ5eVJ12jb3zaeXWU,1100
|
|
51
|
-
langchain_agentx/loop/context/settings.py,sha256=
|
|
52
|
-
langchain_agentx/loop/context/types.py,sha256=
|
|
52
|
+
langchain_agentx/loop/context/settings.py,sha256=EO35T2P5tIUIqkO42ffLTRD-U-w2aRxeAYuHFHYc0nE,6589
|
|
53
|
+
langchain_agentx/loop/context/types.py,sha256=jWXibGiJY6sQnd5-OQu9z7ZZM8Efi1X-6M8zJHNutqw,3637
|
|
53
54
|
langchain_agentx/loop/context/stages/__init__.py,sha256=wk9CFh8_Akw8qs3Dldnx14VE1MhyF5i9Cg3phTVChhg,892
|
|
54
|
-
langchain_agentx/loop/context/stages/autocompact.py,sha256=
|
|
55
|
+
langchain_agentx/loop/context/stages/autocompact.py,sha256=7segcCEl0kk9hK6YRHAbM67e8As1sE_CRaUUfUnHFh0,13581
|
|
55
56
|
langchain_agentx/loop/context/stages/base.py,sha256=LVfCp-DLySrTExy0J-M40tDJvzbOXxfZxXvi7XQayA8,1380
|
|
56
57
|
langchain_agentx/loop/context/stages/collapse.py,sha256=yOf3nfWZr83rq2qnhUpuTCLFHcGvF7my8klMLmfZ7jc,2971
|
|
57
58
|
langchain_agentx/loop/context/stages/microcompact.py,sha256=WnT58w85xcaSzsGEww5TEnU1noAzkao3ZgAARo65a7Y,3142
|
|
@@ -60,7 +61,7 @@ langchain_agentx/loop/context/stages/snip.py,sha256=AZy3D2XPrL1GQU_gE9isKApcphXw
|
|
|
60
61
|
langchain_agentx/loop/context/stages/tool_result_budget.py,sha256=zQcJynRnC8QF30cEDduHkso6jChYjckVcnOjYSrCrtg,3833
|
|
61
62
|
langchain_agentx/loop/exit/__init__.py,sha256=3-CMz5ApkJeBc549vRfgNABenyYKVbib4IdkErVtGcM,528
|
|
62
63
|
langchain_agentx/loop/exit/api_error_detection.py,sha256=QzyMTov4VrkpHmn288Tw7DN00hiyJNXMKlOrCbvsiAA,1479
|
|
63
|
-
langchain_agentx/loop/exit/exit_logic.py,sha256=
|
|
64
|
+
langchain_agentx/loop/exit/exit_logic.py,sha256=3I63n9pyjHD9CfpboWSLNm2O2J8c5PlVjcxesir40k8,14068
|
|
64
65
|
langchain_agentx/loop/exit/query_source.py,sha256=b_VB13zxNbLAqUAuDt1E3SII3jNLagY-FdN6SbczTsI,2082
|
|
65
66
|
langchain_agentx/loop/exit/reason_codes.py,sha256=Nk1x2ipftRIRa4U1Z2goyXXWB9TsPFL9TW6WfvtMCEo,4810
|
|
66
67
|
langchain_agentx/loop/exit/resolution.py,sha256=taIMHzAUtgrQoU9446-CUXBN0PyCujhl6wBQfbxR1qI,1427
|
|
@@ -68,7 +69,7 @@ langchain_agentx/loop/exit/terminal.py,sha256=_DAZk-kS4Xd0nxMlayLo60-uj1Y5ozgBjL
|
|
|
68
69
|
langchain_agentx/loop/exit/withheld_error.py,sha256=LfX3j7Rgd9VoMzlz7GOs9TPuRe7RXr_Gxweyotx3tqQ,1846
|
|
69
70
|
langchain_agentx/loop/graph/__init__.py,sha256=9pUUqn7G87n3lV45iYIU24j0wcTHyCD--SSdtv3urh4,136
|
|
70
71
|
langchain_agentx/loop/graph/builtin_loop_control.py,sha256=31o4H6SDGC_vECSliXecuVEnzlD1ahlVZ5JzEpxYY04,9248
|
|
71
|
-
langchain_agentx/loop/graph/factory.py,sha256
|
|
72
|
+
langchain_agentx/loop/graph/factory.py,sha256=n0lszl2jYBq1G_rzgmt0-0mCmTa3zuTqrVCow4lUMso,109909
|
|
72
73
|
langchain_agentx/loop/graph/graph_edges.py,sha256=kW6Npx-nMIPzcaisCxVPkTwf5Y9GOKy1NWCNkJWeJBQ,47370
|
|
73
74
|
langchain_agentx/loop/graph/reactive_compact_node.py,sha256=633b5hTnR3BK8GBEKWhzOwGB0BQrVRKozNxDomWFjLo,8762
|
|
74
75
|
langchain_agentx/loop/graph/runtime_tools_node.py,sha256=wQkbc0ophyefpPZEc0q1vKoJOIdS4S6d6hSsrkdRLDk,7387
|
|
@@ -217,7 +218,7 @@ langchain_agentx/observability/evaluation/checkers/tool_behavior.py,sha256=o1nH8
|
|
|
217
218
|
langchain_agentx/observability/events/__init__.py,sha256=Zr9Iguf9XsJQLsCJy13YFdBtXHPEnI9aSWXWmA2MisA,1497
|
|
218
219
|
langchain_agentx/observability/events/accumulated_text_scope.py,sha256=M4OvuQTgReF8SFrOmr-M5vyOJpzfvxj_DKD5bVpGb70,3169
|
|
219
220
|
langchain_agentx/observability/events/agent_defaults.py,sha256=gmX0P__lux5xbCb8dtAlVCb3wZ7avaqFleoW4Q5anw4,1187
|
|
220
|
-
langchain_agentx/observability/events/agent_event_projector.py,sha256=
|
|
221
|
+
langchain_agentx/observability/events/agent_event_projector.py,sha256=SthsPhWuM__Bfm3GoxHw-JCoMQ5xgn_eDgi5n4ib6-4,64600
|
|
221
222
|
langchain_agentx/observability/events/api_retry_projection.py,sha256=XGb09sNOi6k1ZGW4YqMLBE8GDxNwNMprk62jV9TS9dQ,2433
|
|
222
223
|
langchain_agentx/observability/events/compact_event_gate.py,sha256=50RJemwB1lnQn_NFWOFSgU418ZUR8dbd_v0538PT7zM,4751
|
|
223
224
|
langchain_agentx/observability/events/factory.py,sha256=gqMATIK9tBQzaPWSPhCCSPuCq-WF562ZDTnFUaMm9Qc,1570
|
|
@@ -766,8 +767,8 @@ langchain_agentx/workspace/root_grant_manager.py,sha256=W3gy8HTevbERbXqIgRcjzOXO
|
|
|
766
767
|
langchain_agentx/workspace/tool_boundary.py,sha256=UDwX6swpSLsx9HNkYuuRRiV5o7ZZG_Bru2Yn0c5kNX8,5724
|
|
767
768
|
langchain_agentx/workspace/validators.py,sha256=tQt-6TOcL8Fw7Ig5ebA9S7vGWh1rby920eFW6x8Tk9E,1439
|
|
768
769
|
langchain_agentx/workspace/view.py,sha256=PGasqTaqhlD03SXXazHuw4RHfV681AIdlsYqL70pEjc,4774
|
|
769
|
-
langchain_agentx_python-2.3.
|
|
770
|
-
langchain_agentx_python-2.3.
|
|
771
|
-
langchain_agentx_python-2.3.
|
|
772
|
-
langchain_agentx_python-2.3.
|
|
773
|
-
langchain_agentx_python-2.3.
|
|
770
|
+
langchain_agentx_python-2.3.4.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
771
|
+
langchain_agentx_python-2.3.4.dist-info/METADATA,sha256=zMKaBp2iVa62_ASW-y0xHpoqDFuMu64NDF414ESG2XA,23942
|
|
772
|
+
langchain_agentx_python-2.3.4.dist-info/WHEEL,sha256=51RkbunBAw4BWsgaQWTpPhg4Diwp3c9P5iaLk67Hdtg,92
|
|
773
|
+
langchain_agentx_python-2.3.4.dist-info/top_level.txt,sha256=Ge284pniNt8xea0OLk2o9o32GqVpDhOYk20fwE-0xxA,17
|
|
774
|
+
langchain_agentx_python-2.3.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{langchain_agentx_python-2.3.3.dist-info → langchain_agentx_python-2.3.4.dist-info}/top_level.txt
RENAMED
|
File without changes
|