langchain-agentx-python 0.9.2__py3-none-any.whl → 0.9.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.
@@ -11,7 +11,7 @@ from langchain_agentx import create_loop_agent
11
11
  ```
12
12
  """
13
13
 
14
- __version__ = "0.9.2"
14
+ __version__ = "0.9.3"
15
15
 
16
16
  from .loop import ( # noqa: F401
17
17
  create_loop_agent,
@@ -22,8 +22,10 @@ from langchain_core.messages import AIMessage
22
22
 
23
23
  from langchain_agentx.loop.exit.reason_codes import (
24
24
  ERROR_TERMINAL_REASONS,
25
+ TERMINAL_REASON_COMPLETED,
25
26
  TERMINAL_REASON_ERROR,
26
27
  TERMINAL_REASON_MAX_TOKENS,
28
+ TRANSITION_API_ERROR_TERMINAL,
27
29
  TRANSITION_CONTEXT_WINDOW_RECOVERY_EXHAUSTED,
28
30
  TRANSITION_MAX_OUTPUT_TOKENS_RECOVERY_EXHAUSTED,
29
31
  TRANSITION_WITHHOLD_RECOVERY_EXHAUSTED,
@@ -117,7 +119,9 @@ class FinishEventPayloadComposer:
117
119
 
118
120
  from langchain_agentx.loop.exit.exit_logic import RECOVERABLE_TERMINAL_REASONS
119
121
 
120
- is_error = self._resolve_is_error(terminal_reason, withheld_error, snap)
122
+ is_error = self._resolve_is_error(
123
+ terminal_reason, withheld_error, snap, messages=messages
124
+ )
121
125
  recoverable = (
122
126
  terminal_reason in RECOVERABLE_TERMINAL_REASONS if terminal_reason else False
123
127
  )
@@ -125,6 +129,14 @@ class FinishEventPayloadComposer:
125
129
  recovery_exhausted = (
126
130
  transition_reason in _RECOVERY_EXHAUSTED_TRANSITIONS if is_error else False
127
131
  )
132
+ if (
133
+ not recovery_exhausted
134
+ and is_error
135
+ and terminal_reason == TERMINAL_REASON_MAX_TOKENS
136
+ and resolve_overflow_kind(withheld_error) == "context_window"
137
+ and bool(snap.get("has_attempted_reactive_compact"))
138
+ ):
139
+ recovery_exhausted = True
128
140
  error_kind = self._infer_error_kind(
129
141
  terminal_reason=terminal_reason,
130
142
  is_error=is_error,
@@ -166,7 +178,14 @@ class FinishEventPayloadComposer:
166
178
  terminal_reason: str | None,
167
179
  withheld_error: dict[str, Any] | None,
168
180
  snap: dict[str, Any],
181
+ *,
182
+ messages: list[Any] | None = None,
169
183
  ) -> bool:
184
+ transition_reason = _transition_reason(snap)
185
+ if transition_reason == TRANSITION_API_ERROR_TERMINAL:
186
+ return True
187
+ if _is_api_error_message(_last_ai_message(messages)):
188
+ return True
170
189
  if terminal_reason in ERROR_TERMINAL_REASONS:
171
190
  return True
172
191
  if isinstance(withheld_error, dict) and withheld_error and snap.get("should_end"):
@@ -185,6 +204,13 @@ class FinishEventPayloadComposer:
185
204
  if not is_error:
186
205
  return None
187
206
 
207
+ last_ai = _last_ai_message(messages)
208
+ if (
209
+ transition_reason == TRANSITION_API_ERROR_TERMINAL
210
+ or _is_api_error_message(last_ai)
211
+ ):
212
+ return "api_error"
213
+
188
214
  overflow_kind = resolve_overflow_kind(withheld_error)
189
215
  if terminal_reason == TERMINAL_REASON_MAX_TOKENS:
190
216
  if overflow_kind == "context_window" or (
@@ -198,9 +224,9 @@ class FinishEventPayloadComposer:
198
224
  return "unknown"
199
225
 
200
226
  if terminal_reason == TERMINAL_REASON_ERROR:
201
- last_ai = _last_ai_message(messages)
202
- if _is_api_error_message(last_ai):
203
- return "api_error"
227
+ return "unknown"
228
+
229
+ if terminal_reason == TERMINAL_REASON_COMPLETED:
204
230
  return "unknown"
205
231
 
206
232
  return "unknown"
@@ -6,12 +6,22 @@ from .conversation_factory import create_conversation_session
6
6
  from .conversation_session import ConversationSession
7
7
  from .factory import create_agent_session
8
8
  from .protocol import LoopContainer
9
+ from .recovery import (
10
+ SessionRecoveryRunResult,
11
+ finish_outcome_from_graph_output,
12
+ parse_result_finish_outcome,
13
+ run_with_recovery_loop,
14
+ )
9
15
 
10
16
  __all__ = [
11
17
  "AgentSession",
12
18
  "ConversationSession",
13
19
  "LoopContainer",
20
+ "SessionRecoveryRunResult",
14
21
  "create_agent_session",
15
22
  "create_conversation_session",
23
+ "finish_outcome_from_graph_output",
16
24
  "load_session_messages",
25
+ "parse_result_finish_outcome",
26
+ "run_with_recovery_loop",
17
27
  ]
@@ -29,8 +29,13 @@ from ..command.builtin import (
29
29
  make_memory_command,
30
30
  make_reload_plugins_command,
31
31
  )
32
- from ..observability.events.finish_outcome import enrich_run_result
32
+ from ..observability.events.finish_outcome import RecoveryPolicyMode, enrich_run_result
33
33
  from ..loop.config import merge_run_config
34
+ from .recovery import (
35
+ SessionRecoveryRunResult,
36
+ finish_outcome_from_graph_output,
37
+ run_with_recovery_loop,
38
+ )
34
39
  from ..loop.context.compaction_service import default_loop_context_compaction
35
40
  from ..loop.context.message_utils import total_estimated_tokens_for_messages
36
41
  from ..loop.hook.types import HookContext, HookEvent
@@ -74,6 +79,7 @@ class AgentSession:
74
79
  self._enable_trace = enable_trace
75
80
  self._transcript_writer = transcript_writer
76
81
  self._last_transcript_uuid: str | None = None
82
+ self._last_finish_outcome: dict[str, Any] | None = None
77
83
  self._session_memory_manager: Any | None = None
78
84
  self._capabilities = capabilities or RuntimeCapabilities.build(
79
85
  resource_root=workspace_cfg.workspace_root,
@@ -119,10 +125,48 @@ class AgentSession:
119
125
  await self._plugin_loader.unload_all()
120
126
 
121
127
  async def run_loop(self, user_input: str) -> dict[str, Any]:
128
+ result = await self._run_loop_turn(user_input=user_input)
129
+ return result
130
+
131
+ async def resume_after_compact(self) -> dict[str, Any]:
132
+ """compact 后重跑当前轮:不再 append 新的 HumanMessage。
133
+
134
+ 适用于 CLI `/compact` 或 headless auto 恢复的第二跳;与 ``run_loop(same_query)``
135
+ 不同,不会把同一用户问题重复写入 messages / transcript。
136
+ """
137
+ return await self._run_loop_turn(user_input=None)
138
+
139
+ async def run_with_recovery(
140
+ self,
141
+ user_input: str,
142
+ *,
143
+ mode: RecoveryPolicyMode = "auto",
144
+ max_outer_retries: int = 1,
145
+ progress_callback: Any = None,
146
+ ) -> SessionRecoveryRunResult:
147
+ """B1 外层自动恢复:recoverable 时 compact + resume,受 ``max_outer_retries`` 约束。
148
+
149
+ - ``mode="auto"``:可恢复且未 exhausted 时自动 compact 并 resume。
150
+ - ``mode="interactive"``:只跑一轮,把 ``RecoveryAction`` 留给 CLI 决策。
151
+ """
152
+ return await run_with_recovery_loop(
153
+ user_input=user_input,
154
+ mode=mode,
155
+ max_outer_retries=max_outer_retries,
156
+ run_new_turn=lambda inp: self._run_loop_turn(user_input=inp),
157
+ resume_current_turn=lambda: self._run_loop_turn(user_input=None),
158
+ compact=self.compact_context,
159
+ progress_callback=progress_callback,
160
+ )
161
+
162
+ async def _run_loop_turn(self, *, user_input: str | None) -> dict[str, Any]:
122
163
  if self._graph is None:
123
164
  raise RuntimeError("AgentSession graph is not initialized")
124
- appended_message = HumanMessage(content=user_input)
125
- self._messages.append(appended_message)
165
+
166
+ appended_message: HumanMessage | None = None
167
+ if user_input is not None:
168
+ appended_message = HumanMessage(content=user_input)
169
+ self._messages.append(appended_message)
126
170
  baseline_count = len(self._messages)
127
171
  run_config = merge_run_config(self._graph, None)
128
172
  try:
@@ -134,20 +178,26 @@ class AgentSession:
134
178
  config=run_config,
135
179
  )
136
180
  except Exception:
137
- # 回滚本轮 append,避免异常路径重复累积 user 消息。
138
- if self._messages and self._messages[-1] is appended_message:
181
+ if appended_message is not None and self._messages and self._messages[-1] is appended_message:
139
182
  self._messages.pop()
140
183
  raise
184
+
141
185
  if isinstance(result, dict) and isinstance(result.get("messages"), list):
142
186
  new_messages = list(result["messages"])
143
187
  self._messages = new_messages
144
- self._append_transcript_message(appended_message)
188
+ if appended_message is not None:
189
+ self._append_transcript_message(appended_message)
145
190
  for message in new_messages[baseline_count:]:
146
191
  self._append_transcript_message(message)
147
192
  self._active_files.extend(self._extract_accessed_files(result))
193
+
194
+ enriched: dict[str, Any]
148
195
  if isinstance(result, dict):
149
- return enrich_run_result(dict(result))
150
- return dict(result) if isinstance(result, dict) else {"result": result}
196
+ enriched = enrich_run_result(dict(result))
197
+ else:
198
+ enriched = {"result": result}
199
+ self._last_finish_outcome = enriched.get("finish_outcome")
200
+ return enriched
151
201
 
152
202
  async def stream_loop_events(
153
203
  self,
@@ -161,6 +211,10 @@ class AgentSession:
161
211
  说明:
162
212
  该方法用于需要 astream_events 的场景(如 SSE),执行完成后会尝试
163
213
  从 on_chain_end(LangGraph) 事件回填消息列表,保持与 run_loop 一致的上下文累积语义。
214
+
215
+ 契约:
216
+ ``last_finish_outcome`` 仅在事件流完整消费到 ``on_chain_end(name=LangGraph)``
217
+ 后可靠;中途 break / 异常时可能仍为 None 或上一轮快照。
164
218
  """
165
219
  if self._graph is None:
166
220
  raise RuntimeError("AgentSession graph is not initialized")
@@ -168,6 +222,7 @@ class AgentSession:
168
222
  self._messages.append(appended_message)
169
223
  baseline_count = len(self._messages)
170
224
  output_messages: list[Any] | None = None
225
+ graph_output: dict[str, Any] | None = None
171
226
  run_config = merge_run_config(self._graph, config)
172
227
  try:
173
228
  async for event in self._graph.astream_events(
@@ -181,6 +236,8 @@ class AgentSession:
181
236
  if event.get("event") == "on_chain_end" and event.get("name") == "LangGraph":
182
237
  data = event.get("data", {}) or {}
183
238
  output = data.get("output")
239
+ if isinstance(output, dict):
240
+ graph_output = dict(output)
184
241
  if isinstance(output, dict) and isinstance(output.get("messages"), list):
185
242
  output_messages = list(output["messages"])
186
243
  yield event
@@ -193,6 +250,21 @@ class AgentSession:
193
250
  self._append_transcript_message(appended_message)
194
251
  for message in output_messages[baseline_count:]:
195
252
  self._append_transcript_message(message)
253
+ if graph_output is not None:
254
+ self._last_finish_outcome = finish_outcome_from_graph_output(graph_output)
255
+ if isinstance(graph_output.get("_accessed_files"), list):
256
+ self._active_files.extend(
257
+ [item for item in graph_output["_accessed_files"] if isinstance(item, str)]
258
+ )
259
+
260
+ @property
261
+ def last_finish_outcome(self) -> dict[str, Any] | None:
262
+ """最近一次 run_loop / resume / stream 结束后的 finish_outcome 快照。
263
+
264
+ 流式路径:仅当 ``stream_loop_events`` 完整消费到 LangGraph ``on_chain_end`` 后更新;
265
+ 中途中断时可能为 None 或 stale,勿当作本轮终态。
266
+ """
267
+ return self._last_finish_outcome
196
268
 
197
269
  @property
198
270
  def active_files(self) -> list[str]:
@@ -347,4 +419,4 @@ class AgentSession:
347
419
  self._runtime_command_registry.register(make_reload_plugins_command())
348
420
 
349
421
 
350
- __all__ = ["AgentSession"]
422
+ __all__ = ["AgentSession", "SessionRecoveryRunResult"]
@@ -0,0 +1,111 @@
1
+ """
2
+ session/recovery.py — AgentSession 外层恢复编排(B1 auto / interactive 分流)
3
+
4
+ 职责:
5
+ 在 run_loop + compact_context 之上封装「compact 后继续同一问题」与 auto 模式重试预算,
6
+ 避免消费方重复 append 同一条 HumanMessage。
7
+
8
+ 链路位置:
9
+ AgentSession.run_with_recovery / resume_after_compact → 本模块
10
+
11
+ 当前裁剪范围:
12
+ - 不做图内 reactive_compact 拓扑修复(见 release 文档缺口 2)
13
+ - 不做 B2 透明自恢复(单次 invoke 内无感知恢复)
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from dataclasses import dataclass
19
+ from typing import Any, Awaitable, Callable, Protocol
20
+
21
+ from langchain_agentx.observability.events.finish_outcome import (
22
+ FinishOutcome,
23
+ FinishOutcomeParser,
24
+ RecoveryAction,
25
+ RecoveryActionResolver,
26
+ RecoveryPolicyMode,
27
+ )
28
+
29
+
30
+ class _CompactCallable(Protocol):
31
+ async def __call__(self, *, progress_callback: Any = None) -> tuple[int, int]: ...
32
+
33
+
34
+ class _RunOnceCallable(Protocol):
35
+ async def __call__(self) -> dict[str, Any]: ...
36
+
37
+
38
+ @dataclass(frozen=True)
39
+ class SessionRecoveryRunResult:
40
+ """run_with_recovery 返回:最后一轮 graph 结果 + 终态语义 + 外层 compact 次数。"""
41
+
42
+ result: dict[str, Any]
43
+ outcome: FinishOutcome
44
+ action: RecoveryAction
45
+ outer_recovery_attempts: int
46
+
47
+
48
+ def parse_result_finish_outcome(result: dict[str, Any]) -> FinishOutcome:
49
+ raw = result.get("finish_outcome")
50
+ if isinstance(raw, dict):
51
+ return FinishOutcomeParser().parse_finish_data(raw)
52
+ return FinishOutcomeParser().from_loop_state(result)
53
+
54
+
55
+ def finish_outcome_from_graph_output(output: dict[str, Any] | None) -> dict[str, Any]:
56
+ """从 LangGraph on_chain_end output 构建 finish_outcome 字典(流式路径)。"""
57
+ if not isinstance(output, dict):
58
+ return FinishOutcomeParser().from_loop_state({}).to_dict()
59
+ outcome = FinishOutcomeParser().from_loop_state(output)
60
+ return outcome.to_dict()
61
+
62
+
63
+ async def run_with_recovery_loop(
64
+ *,
65
+ user_input: str,
66
+ mode: RecoveryPolicyMode,
67
+ max_outer_retries: int,
68
+ run_new_turn: Callable[[str], Awaitable[dict[str, Any]]],
69
+ resume_current_turn: Callable[[], Awaitable[dict[str, Any]]],
70
+ compact: _CompactCallable,
71
+ progress_callback: Any = None,
72
+ ) -> SessionRecoveryRunResult:
73
+ """B1 外层编排:首轮 run_new_turn;recoverable 时 compact + resume(不重复 append)。"""
74
+ if max_outer_retries < 0:
75
+ raise ValueError("max_outer_retries must be >= 0")
76
+
77
+ result = await run_new_turn(user_input)
78
+ outcome = parse_result_finish_outcome(result)
79
+ action = RecoveryActionResolver.resolve(outcome, mode=mode)
80
+ attempts = 0
81
+
82
+ while attempts < max_outer_retries:
83
+ if outcome.succeeded:
84
+ break
85
+ if RecoveryActionResolver.blocks_auto_compact(outcome):
86
+ break
87
+ if mode == "interactive":
88
+ break
89
+ resolved = RecoveryActionResolver.resolve(outcome, mode="auto")
90
+ if resolved != RecoveryAction.AUTO_COMPACT:
91
+ break
92
+ await compact(progress_callback=progress_callback)
93
+ attempts += 1
94
+ result = await resume_current_turn()
95
+ outcome = parse_result_finish_outcome(result)
96
+ action = RecoveryActionResolver.resolve(outcome, mode=mode)
97
+
98
+ return SessionRecoveryRunResult(
99
+ result=result,
100
+ outcome=outcome,
101
+ action=action,
102
+ outer_recovery_attempts=attempts,
103
+ )
104
+
105
+
106
+ __all__ = [
107
+ "SessionRecoveryRunResult",
108
+ "finish_outcome_from_graph_output",
109
+ "parse_result_finish_outcome",
110
+ "run_with_recovery_loop",
111
+ ]
@@ -52,6 +52,12 @@ _WORKTREES_SEGMENT = "worktrees"
52
52
  # agent_home_segment 下需 ask 的子目录(对齐 isClaudeConfigFilePath 的 commands/agents/skills)
53
53
  _AGENT_CONFIG_SUBDIRS: tuple[str, ...] = ("commands", "agents", "skills")
54
54
 
55
+ # agent_home 下允许静默写入的子目录(对齐 CC checkEditableInternalPath)。
56
+ # 与 agent_home_segment 绑定:.langchain_agentx / .claude / .cursor 均适用 memory/、sessions/。
57
+ _AGENT_INTERNAL_WRITABLE_SUBDIRS: frozenset[str] = frozenset(
58
+ {"memory", "sessions", "worktrees"}
59
+ )
60
+
55
61
  _IDE_SETTINGS_PARENTS: tuple[str, ...] = (".vscode", ".cursor")
56
62
 
57
63
 
@@ -104,7 +110,6 @@ class PathSafetyEvaluator:
104
110
  s.lower() for s in (*config.dangerous_directory_segments, config.agent_home_segment)
105
111
  )
106
112
  self._agent_home_lower = home
107
- self._worktrees_lower = config.worktrees_segment.lower()
108
113
 
109
114
  def evaluate_unc_path(self, path: str) -> AuthorizationDecision | None:
110
115
  """UNC / extended-length 前缀:Read 与 Write 均先拦截(CC 对齐)。"""
@@ -162,7 +167,7 @@ class PathSafetyEvaluator:
162
167
  continue
163
168
  if seg_lower == self._agent_home_lower:
164
169
  next_part = parts[i + 1] if i + 1 < len(parts) else None
165
- if next_part and next_part.lower() == self._worktrees_lower:
170
+ if next_part and next_part.lower() in _AGENT_INTERNAL_WRITABLE_SUBDIRS:
166
171
  continue
167
172
  return True
168
173
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langchain-agentx-python
3
- Version: 0.9.2
3
+ Version: 0.9.3
4
4
  Summary: LangChain/LangGraph-based agent utilities for CodeBaseX.
5
5
  Author-email: GoodMood2008 <GoodMood2008@users.noreply.github.com>
6
6
  License: Apache License
@@ -1,4 +1,4 @@
1
- langchain_agentx/__init__.py,sha256=4oNeIhyUNvA5YPBckofqFZOSSgna20e6Gb0DkhjQaDg,1678
1
+ langchain_agentx/__init__.py,sha256=Xm0Q5GvkbAI2yNpAGB84U70PzzdX-ai12e_4gFGtVto,1678
2
2
  langchain_agentx/command/__init__.py,sha256=Ej260S5uFQcmEtGZQG_NH7BYjHoStrpBLtGUsBTxyZk,631
3
3
  langchain_agentx/command/context.py,sha256=DIGOGPBw5UGDBm0WNNJlKx1h_9rCRmcdROv4DT61Qug,731
4
4
  langchain_agentx/command/dispatcher.py,sha256=72gRi20Gqv3b96MZygKfJX635AnPcFNuZOOh01n3Wm0,7309
@@ -137,7 +137,7 @@ langchain_agentx/observability/evaluation/checkers/exit_quality.py,sha256=kcV2VY
137
137
  langchain_agentx/observability/evaluation/checkers/session_memory.py,sha256=jYDdIDUAhYktggsymkBADBunrSbxdC66veM-tZt3a3s,1579
138
138
  langchain_agentx/observability/evaluation/checkers/tool_behavior.py,sha256=o1nH8SeE9145H7ej4naahRcmgw_9st21dY1W3IQa2sg,2097
139
139
  langchain_agentx/observability/events/__init__.py,sha256=4z4AIMSU8QrtsW_siEN6QkfMGwcxqbOcWYdqh8wYxy0,794
140
- langchain_agentx/observability/events/finish_event_payload_composer.py,sha256=Pabh1Fd9VZPxBbvkxmvk58QeQFYbwySp7D-8vBKDYX0,8905
140
+ langchain_agentx/observability/events/finish_event_payload_composer.py,sha256=b7RKImz5eWtqx0cezk2m3epT4pljPmqW7mJlgZhYC3o,9781
141
141
  langchain_agentx/observability/events/finish_outcome.py,sha256=VIzDUfvK9htoi9UOJN7TWzRszUHL2Nle5H6dxmYWnKo,7049
142
142
  langchain_agentx/observability/events/langchain_agentx_event_adapter.py,sha256=w9BuAJ6dvduCDUdH93OSzeQJAjRZId7mJRQJmoAM6XQ,55020
143
143
  langchain_agentx/observability/logging/__init__.py,sha256=mDtPOxYZZFx8ezQCSwnmnfrdVi305DeJFzThwHBtnrY,508
@@ -198,13 +198,14 @@ langchain_agentx/provider/semantics/families/openai_codec.py,sha256=RmzLq_LR1n3o
198
198
  langchain_agentx/provider/semantics/families/openai_finish_reason.py,sha256=t5ebGN2JMxUYPm8Jw8uebOgdAPc20GPgUiKJVja5r7U,1993
199
199
  langchain_agentx/provider/semantics/families/openai_interpreter.py,sha256=zT7EFfHJ5fmYZ_F59vDfyrYdEwcMJANxkoW1Pt3iocI,1915
200
200
  langchain_agentx/provider/semantics/families/openai_normalizer.py,sha256=oaf2Riz8EY6VQpc6SNKtsb-naMELw3gYV3IsnZoRBYU,2155
201
- langchain_agentx/session/__init__.py,sha256=UO-bRS9oYSzdYoavow4FSXdY7qzw5O3VoUH9_FTzGTI,497
202
- langchain_agentx/session/agent_session.py,sha256=uSuu3Ap76ovKun2PrHANVsXjXRj4c8B3gbRVEIfY9tA,14567
201
+ langchain_agentx/session/__init__.py,sha256=x8RCR4gBO5vC5QPfPxPVB-aXJNzOykWvPlWP0NhZ9eU,789
202
+ langchain_agentx/session/agent_session.py,sha256=TfTXRnWtK5cGFt-ZptGx274FxjlvR-d2ZEFF80IJRtw,17619
203
203
  langchain_agentx/session/conversation_factory.py,sha256=nZYRAwmQDgD7ll99KO929Z_Zc4i2dpZ0bePCZuKgyq8,6683
204
204
  langchain_agentx/session/conversation_recovery.py,sha256=U0M3p4NKaSz6heEvNzlzehC8oTX9EB2Vz-QdYhhyk0U,5813
205
205
  langchain_agentx/session/conversation_session.py,sha256=4iVaEdGll5RO4WHepvVicT1_nDVSBzHg_igNQg2FJ-o,8203
206
206
  langchain_agentx/session/factory.py,sha256=IYoON1w-7NQ7RJTW43_0tg9bONOGYtbo56jZngB37A4,7260
207
207
  langchain_agentx/session/protocol.py,sha256=uNkNiQ2MD9ReJgPaYe5bF0x6JzVqv2TL-hAG8ME1Obs,622
208
+ langchain_agentx/session/recovery.py,sha256=p-h1KRS3Qblng4REcyfCkQlrb-sta5Oc_mSk9meHFHo,3625
208
209
  langchain_agentx/task_runtime/__init__.py,sha256=B9OoHXkyJRURhupkwEtUbEUN1BLOH0rWjkhvc6qdCEo,3513
209
210
  langchain_agentx/task_runtime/core/__init__.py,sha256=D5Y5TDp4oh7ml4O-sVdm8r-3-kEDJ7SJmPK7M6vy8_Y,1094
210
211
  langchain_agentx/task_runtime/core/ids.py,sha256=g19BWz6IK6YYyiuW3AU0HaaQGFjBzDue_ZCT8n_lip0,876
@@ -299,7 +300,7 @@ langchain_agentx/tool_runtime/loop_runtime_context.py,sha256=HBZMdtKD7MpU8o7JmUR
299
300
  langchain_agentx/tool_runtime/messages.py,sha256=Fp-ZiLAbOQAQa8uIv-owE8PXtWyhpYSXxtzy3PVbKSw,3631
300
301
  langchain_agentx/tool_runtime/models.py,sha256=Xc1kEi4n6bqgWBKriNWQyBy2_g4nJkziBu-IKW5HlT0,17721
301
302
  langchain_agentx/tool_runtime/override.py,sha256=GE_i0J3O7RmfmeSdnQ95FGdTZ4Fu8TdfqXlVjfn0J3w,10422
302
- langchain_agentx/tool_runtime/path_safety.py,sha256=vOCIo3F0dwQHDAnS-A5BHwiiCiEv_O84DdWBJ790apI,6360
303
+ langchain_agentx/tool_runtime/path_safety.py,sha256=kTTKlhPr1wxDDXUikd3vf-0IYa8Tt3Yi3NcYH6V-a7s,6607
303
304
  langchain_agentx/tool_runtime/permission_context.py,sha256=R5JxV-6XSmjUjIOJ9YgERoidYcCGyQDPCvuedfIPq1c,4803
304
305
  langchain_agentx/tool_runtime/permission_decision.py,sha256=u1ju2Y0QkjyvquGG1FBBU2wdwbJPz3oJVhcpj4t-vs8,4828
305
306
  langchain_agentx/tool_runtime/pipeline.py,sha256=zvEyhVseD0h5LeZpZiref7VFNwV4qcMkGoG3tcP7q6M,47345
@@ -556,8 +557,8 @@ langchain_agentx/workspace/root_grant_manager.py,sha256=W3gy8HTevbERbXqIgRcjzOXO
556
557
  langchain_agentx/workspace/tool_boundary.py,sha256=3b4KwMrGhsS_HZaoCjytJJk39pN0lN3nvYQIj1vLD1k,3327
557
558
  langchain_agentx/workspace/validators.py,sha256=tQt-6TOcL8Fw7Ig5ebA9S7vGWh1rby920eFW6x8Tk9E,1439
558
559
  langchain_agentx/workspace/view.py,sha256=Ip02CZNI-ZjF5k0OYT3q7RUR_auMEw83VJ6rQsaBcYU,4588
559
- langchain_agentx_python-0.9.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
560
- langchain_agentx_python-0.9.2.dist-info/METADATA,sha256=EU6AGAv0stLj-nWlj6BcZYdvw-09p2RaOX-xGCvJwn0,21468
561
- langchain_agentx_python-0.9.2.dist-info/WHEEL,sha256=51RkbunBAw4BWsgaQWTpPhg4Diwp3c9P5iaLk67Hdtg,92
562
- langchain_agentx_python-0.9.2.dist-info/top_level.txt,sha256=Ge284pniNt8xea0OLk2o9o32GqVpDhOYk20fwE-0xxA,17
563
- langchain_agentx_python-0.9.2.dist-info/RECORD,,
560
+ langchain_agentx_python-0.9.3.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
561
+ langchain_agentx_python-0.9.3.dist-info/METADATA,sha256=5z9zWacixOCy3OxF66ONnRM_H-HDppjwU-ksxsIxqMA,21468
562
+ langchain_agentx_python-0.9.3.dist-info/WHEEL,sha256=51RkbunBAw4BWsgaQWTpPhg4Diwp3c9P5iaLk67Hdtg,92
563
+ langchain_agentx_python-0.9.3.dist-info/top_level.txt,sha256=Ge284pniNt8xea0OLk2o9o32GqVpDhOYk20fwE-0xxA,17
564
+ langchain_agentx_python-0.9.3.dist-info/RECORD,,