langchain-agentx-python 1.2.2__py3-none-any.whl → 1.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.
@@ -11,7 +11,7 @@ from langchain_agentx import create_loop_agent
11
11
  ```
12
12
  """
13
13
 
14
- __version__ = "1.2.2"
14
+ __version__ = "1.2.3"
15
15
 
16
16
  from .loop import ( # noqa: F401
17
17
  create_loop_agent,
@@ -43,11 +43,13 @@ class PromptConfig:
43
43
  - QueryParams.systemPrompt → system
44
44
  - options.customSystemPrompt → override_system
45
45
  - options.appendSystemPrompt → append_system
46
+ - options.thinkingConfig → thinking_enabled
46
47
  """
47
48
  system: str | SystemMessage | None = None
48
49
  override_system: str | None = None
49
50
  append_system: str | None = None
50
51
  dynamic_sections: tuple[SystemPromptSection, ...] = ()
52
+ thinking_enabled: bool = True # 是否启用 thinking(对齐 CC thinkingConfig)
51
53
 
52
54
 
53
55
  @dataclass(frozen=True)
@@ -0,0 +1,105 @@
1
+ """loop/config/thinking_config.py — Thinking 生成配置
2
+
3
+ 职责:
4
+ 定义 ThinkingConfig 数据类,根据 subagent mode (plain/fork/coordinate)
5
+ 决定是否启用 thinking 功能。
6
+
7
+ 链路位置:
8
+ SubagentOrchestrator → ThinkingConfig.from_subagent_mode() →
9
+ SubagentContext.thinking_enabled → AgentLoopConfig
10
+
11
+ 当前裁剪范围:
12
+ v1 基础实现:mode 驱动启用/禁用;预留父配置覆盖路径。
13
+
14
+ CC 对齐:
15
+ - runAgent.ts:682-683: plain mode 默认 { type: 'disabled' }
16
+ - fork mode 继承父配置或默认启用
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from dataclasses import dataclass
22
+ from typing import Any, Literal
23
+
24
+
25
+ @dataclass(frozen=True)
26
+ class ThinkingConfig:
27
+ """Thinking 生成配置(对齐 CC thinkingConfig)。
28
+
29
+ Attributes:
30
+ enabled: 是否启用 thinking
31
+ type: Thinking 类型(预留,对齐 CC { type: 'enabled' | 'disabled' })
32
+ budget_tokens: Thinking token 预算(预留)
33
+ """
34
+ enabled: bool = True
35
+ type: Literal["enabled", "disabled", "auto"] = "auto"
36
+ budget_tokens: int | None = None
37
+
38
+ @classmethod
39
+ def disabled(cls) -> "ThinkingConfig":
40
+ """返回禁用配置(对齐 CC { type: 'disabled' })。"""
41
+ return cls(enabled=False, type="disabled")
42
+
43
+ @classmethod
44
+ def enabled_config(cls) -> "ThinkingConfig":
45
+ """返回启用配置(对齐 CC { type: 'enabled' })。"""
46
+ return cls(enabled=True, type="enabled")
47
+
48
+ @classmethod
49
+ def from_subagent_mode(
50
+ cls,
51
+ mode: str,
52
+ parent_thinking_config: Any | None = None,
53
+ *,
54
+ parent_thinking_enabled: bool | None = None,
55
+ ) -> "ThinkingConfig":
56
+ """根据 subagent mode 决定是否启用 thinking。
57
+
58
+ CC 对齐规则:
59
+ - plain mode: 禁用 thinking(除非父配置显式启用)
60
+ - fork mode: 继承父 thinking_enabled / thinkingConfig(对齐 runAgent useExactTools)
61
+ - coordinate mode: 同 fork,继承父配置
62
+
63
+ Args:
64
+ mode: Subagent 模式 ("plain" | "fork" | "coordinate")
65
+ parent_thinking_config: 父 ThinkingConfig 或 dict(优先于 mode 规则)
66
+ parent_thinking_enabled: 父 ToolExecutionContext.thinking_enabled(fork/coordinate 继承)
67
+
68
+ Returns:
69
+ ThinkingConfig 实例
70
+ """
71
+ # 优先级 1:父显式 thinkingConfig
72
+ if parent_thinking_config is not None:
73
+ if isinstance(parent_thinking_config, dict):
74
+ parent_enabled = parent_thinking_config.get("enabled", True)
75
+ parent_type = parent_thinking_config.get("type", "auto")
76
+ return cls(
77
+ enabled=parent_enabled,
78
+ type=parent_type if parent_type in ("enabled", "disabled", "auto") else "auto",
79
+ )
80
+ elif isinstance(parent_thinking_config, ThinkingConfig):
81
+ return parent_thinking_config
82
+
83
+ # 优先级 2:mode 规则
84
+ if mode == "plain":
85
+ return cls.disabled()
86
+
87
+ # fork / coordinate:继承父 loop thinking_enabled(CC fork inherit)
88
+ if parent_thinking_enabled is not None:
89
+ enabled = bool(parent_thinking_enabled)
90
+ return cls(
91
+ enabled=enabled,
92
+ type="enabled" if enabled else "disabled",
93
+ )
94
+
95
+ return cls.enabled_config()
96
+
97
+ def to_dict(self) -> dict[str, Any]:
98
+ """转换为字典(传递给 Provider)。"""
99
+ return {
100
+ "enabled": self.enabled,
101
+ "type": self.type,
102
+ }
103
+
104
+
105
+ __all__ = ["ThinkingConfig"]
@@ -0,0 +1,58 @@
1
+ """loop/config/ui_display_context.py — UI 展示意图(CLI → SDK seam)
2
+
3
+ 职责:
4
+ 定义宿主(CLI)注入的 transcript / verbose / thinking 展示意图;
5
+ 供 ToolExecutionContext 与 SubagentOrchestrator 读取。
6
+
7
+ 链路位置:
8
+ RunnableConfig.configurable["ui_display_context"] → LangChainAdapter → ToolExecutionContext
9
+
10
+ 当前裁剪范围:
11
+ 仅数据契约与解析;不做 TUI 渲染(langchain_agentx_cli 职责)。
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from dataclasses import dataclass
17
+ from typing import Any, Mapping
18
+
19
+
20
+ @dataclass(frozen=True)
21
+ class UiDisplayContext:
22
+ """宿主 UI 展示意图(对齐 CC verbose + isTranscriptMode)。"""
23
+
24
+ is_transcript_mode: bool = False
25
+ verbose: bool = False
26
+ thinking_enabled: bool | None = None
27
+
28
+ @classmethod
29
+ def from_mapping(cls, raw: Mapping[str, Any] | None) -> UiDisplayContext | None:
30
+ if not raw or not isinstance(raw, Mapping):
31
+ return None
32
+ is_transcript = bool(raw.get("is_transcript_mode", False))
33
+ verbose = bool(raw.get("verbose", False))
34
+ thinking_raw = raw.get("thinking_enabled")
35
+ thinking_enabled = None if thinking_raw is None else bool(thinking_raw)
36
+ return cls(
37
+ is_transcript_mode=is_transcript,
38
+ verbose=verbose,
39
+ thinking_enabled=thinking_enabled,
40
+ )
41
+
42
+ @classmethod
43
+ def from_configurable(cls, configurable: Mapping[str, Any] | None) -> UiDisplayContext | None:
44
+ if not configurable:
45
+ return None
46
+ raw = configurable.get("ui_display_context")
47
+ if isinstance(raw, UiDisplayContext):
48
+ return raw
49
+ if isinstance(raw, Mapping):
50
+ return cls.from_mapping(raw)
51
+ return None
52
+
53
+ def should_show_thinking_full(self) -> bool:
54
+ """对齐 CC Message.tsx:verbose || isTranscriptMode 时展示完整 thinking。"""
55
+ return self.verbose or self.is_transcript_mode
56
+
57
+
58
+ __all__ = ["UiDisplayContext"]
@@ -302,6 +302,7 @@ def _flatten_config_for_runtime(config: AgentLoopConfig) -> _FlatLoopConfig:
302
302
  model_profile_registry=config.model_profile_registry,
303
303
  compact_buffer_tokens=config.compact_buffer_tokens,
304
304
  max_output_tokens_reserved=config.max_output_tokens_reserved,
305
+ thinking_enabled=config.prompt.thinking_enabled,
305
306
  )
306
307
 
307
308
 
@@ -447,6 +447,38 @@ class ModelNode(Runnable):
447
447
  store = (config.get("configurable", {}) or {}).get("session_store")
448
448
  return get_effort_override(store)
449
449
 
450
+ @staticmethod
451
+ def _get_thinking_enabled_from_config(config: RunnableConfig | None) -> bool | None:
452
+ """从 runtime config 读取 thinking_enabled intent(bool,非 vendor kwargs)。"""
453
+ if not isinstance(config, dict):
454
+ return None
455
+ configurable = config.get("configurable", {}) or {}
456
+ loop_config = configurable.get("loop_config")
457
+ if loop_config is not None and hasattr(loop_config, "get"):
458
+ return bool(loop_config.get("thinking_enabled", True))
459
+ return None
460
+
461
+ @staticmethod
462
+ def _thinking_invoke_kwargs(model: Any, config: RunnableConfig | None) -> dict[str, Any]:
463
+ """按 provider family 决定是否在 invoke 时传入 Claude thinking kwargs。
464
+
465
+ 对实际 invoke 目标做 unwrap(Corrector / RunnableBinding),避免外层 wrapper
466
+ 导致 family 误判从而跳过 thinking。
467
+ """
468
+ thinking_enabled = ModelNode._get_thinking_enabled_from_config(config)
469
+ if thinking_enabled is None:
470
+ return {}
471
+ from langchain_agentx.provider.semantics.profile import (
472
+ get_default_profile_resolver,
473
+ unwrap_chat_model_for_profile,
474
+ )
475
+
476
+ chat_model = unwrap_chat_model_for_profile(model)
477
+ profile = get_default_profile_resolver().resolve_from_model_instance(chat_model)
478
+ if profile.family != "anthropic":
479
+ return {}
480
+ return {"thinking": {"type": "enabled" if thinking_enabled else "disabled"}}
481
+
450
482
  # ===== 模型调用 =====
451
483
 
452
484
  def _invoke_bound(self, req: Any, *, config: RunnableConfig | None = None) -> Any:
@@ -465,7 +497,8 @@ class ModelNode(Runnable):
465
497
  )
466
498
  model_ = self._bind_llm_callback_handler(model_, config)
467
499
  messages = _messages_for_model_invoke(req)
468
- output = model_.invoke(messages, config=config)
500
+ thinking_kwargs = self._thinking_invoke_kwargs(model_, config)
501
+ output = model_.invoke(messages, config=config, **thinking_kwargs)
469
502
  if self._name:
470
503
  output.name = self._name
471
504
  handled_output = handle_model_output(
@@ -496,7 +529,8 @@ class ModelNode(Runnable):
496
529
  )
497
530
  model_ = self._bind_llm_callback_handler(model_, config)
498
531
  messages = _messages_for_model_invoke(req)
499
- output = await model_.ainvoke(messages, config=config)
532
+ thinking_kwargs = self._thinking_invoke_kwargs(model_, config)
533
+ output = await model_.ainvoke(messages, config=config, **thinking_kwargs)
500
534
  if self._name:
501
535
  output.name = self._name
502
536
  handled_output = handle_model_output(
@@ -27,7 +27,7 @@ import shutil
27
27
  import uuid
28
28
  from collections.abc import Callable
29
29
  from dataclasses import dataclass, field
30
- from typing import Any
30
+ from typing import Any, Literal
31
31
 
32
32
  from langchain_agentx.loop.context.query_source import LoopCompilationContext, QuerySource
33
33
  from langchain_agentx.loop.runtime.subagent_execution_paths import (
@@ -97,6 +97,10 @@ class SubagentContext:
97
97
  can_use_tool: Callable[[str, dict[str, Any]], bool] | None = None
98
98
  register_transcript: bool = True
99
99
 
100
+ # Thinking 与显示控制字段(对齐 CC thinkingConfig + isTranscriptMode)
101
+ thinking_enabled: bool = True # 是否启用 thinking(默认启用,plain mode 会被禁用)
102
+ display_mode: Literal["default", "transcript"] = "default" # 显示模式(transcript 显示详细内容)
103
+
100
104
 
101
105
  @dataclass
102
106
  class SubagentResult:
@@ -137,6 +141,8 @@ def create_subagent_context(
137
141
  fork_worktree_parent_cwd: str | None = None,
138
142
  fork_worktree_path: str | None = None,
139
143
  available_tools: list[Any] | None = None,
144
+ thinking_enabled: bool = True,
145
+ display_mode: Literal["default", "transcript"] = "default",
140
146
  ) -> SubagentContext:
141
147
  """工厂函数:从父上下文创建子 Agent 上下文
142
148
 
@@ -158,6 +164,8 @@ def create_subagent_context(
158
164
  在最终任务 user 消息前插入 CC 等价 worktree 提示(父 cwd 由 ``fork_worktree_parent_cwd`` 提供)。
159
165
  fork_worktree_parent_cwd: 父 Agent 工作目录(须在 ``run_with_cwd_override`` 子 cwd 生效前由编排层捕获)。
160
166
  fork_worktree_path: 子 Agent 的 worktree 根路径(通常即 ``path_prep.worktree_dir``)。
167
+ thinking_enabled: 是否启用 thinking(由 SubagentOrchestrator 根据 mode 决定)
168
+ display_mode: 显示模式("default" | "transcript")
161
169
 
162
170
  Returns:
163
171
  SubagentContext 实例
@@ -291,6 +299,8 @@ def create_subagent_context(
291
299
  capabilities=getattr(parent_ctx, "capabilities", None),
292
300
  runnable_config=getattr(parent_ctx, "runnable_config", None),
293
301
  available_tools=list(available_tools or []),
302
+ thinking_enabled=thinking_enabled,
303
+ display_mode=display_mode,
294
304
  )
295
305
 
296
306
 
@@ -0,0 +1,45 @@
1
+ """loop/subagent/display_projector.py — Subagent execution_trace → UI 投影
2
+
3
+ 职责:
4
+ 将 SubagentExecutionTrace 投影为 present_for_display 的 tool_calls 列表;
5
+ default 摘要 / transcript 全量由 display_mode 决定(trace 对象内仍全量)。
6
+
7
+ 链路位置:
8
+ AgentRuntimeTool.present_for_display → SubagentDisplayProjector
9
+
10
+ 当前裁剪范围:
11
+ 仅 dict 投影;不渲染 TUI。
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from typing import Any, Literal
17
+
18
+ from langchain_agentx.loop.subagent.progress import SubagentExecutionTrace
19
+
20
+
21
+ class SubagentDisplayProjector:
22
+ """execution_trace → present_for_display 字段投影。"""
23
+
24
+ @staticmethod
25
+ def project_tool_calls(
26
+ trace: SubagentExecutionTrace,
27
+ *,
28
+ display_mode: Literal["default", "transcript"] | None = None,
29
+ ) -> list[dict[str, Any]]:
30
+ mode = display_mode if display_mode is not None else trace.display_mode
31
+ return trace.to_dict_list(display_mode=mode)
32
+
33
+ @staticmethod
34
+ def resolve_display_mode(
35
+ trace: SubagentExecutionTrace | None,
36
+ ctx_display_mode: Literal["default", "transcript"] | None = None,
37
+ ) -> Literal["default", "transcript"]:
38
+ if ctx_display_mode in ("default", "transcript"):
39
+ return ctx_display_mode
40
+ if trace is not None:
41
+ return trace.display_mode
42
+ return "default"
43
+
44
+
45
+ __all__ = ["SubagentDisplayProjector"]
@@ -65,7 +65,10 @@ def create_subagent_graph(
65
65
  # Phase 3: config-first 模式
66
66
  config = AgentLoopConfig(
67
67
  session_id=session_id,
68
- prompt=PromptConfig(system=ctx.system_prompt or None),
68
+ prompt=PromptConfig(
69
+ system=ctx.system_prompt or None,
70
+ thinking_enabled=ctx.thinking_enabled,
71
+ ),
69
72
  workspace=AgentStateConfig(
70
73
  workspace_root=ctx.workspace_root or None,
71
74
  agent_home_segment=ctx.agent_home_segment,
@@ -14,7 +14,7 @@ from __future__ import annotations
14
14
  import logging
15
15
  import os
16
16
  import uuid
17
- from typing import TYPE_CHECKING, Any
17
+ from typing import TYPE_CHECKING, Any, Literal
18
18
 
19
19
  from langchain_agentx.loop.runtime import RuntimeContextFactory, SubagentContextOverrides
20
20
  from langchain_agentx.loop.runtime.subagent_execution_paths import (
@@ -41,6 +41,7 @@ from langchain_agentx.loop.subagent.runner import (
41
41
  from langchain_agentx.loop.subagent.async_runner import register_background_agent
42
42
  from langchain_agentx.observability.logging import ObservabilityLoggerAdapter, build_log_context
43
43
  from langchain_agentx.workspace import resolve_agent_state_config
44
+ from langchain_agentx.loop.config.thinking_config import ThinkingConfig
44
45
 
45
46
  if TYPE_CHECKING:
46
47
  from langchain_agentx.loop.runtime import AgentLoopConfig
@@ -71,6 +72,39 @@ class SubagentOrchestrator:
71
72
  self._mode = mode
72
73
  self._background_output_dir = background_output_dir
73
74
 
75
+ def _resolve_thinking_enabled(
76
+ self,
77
+ parent_ctx: "ToolExecutionContext",
78
+ ) -> bool:
79
+ """解析 subagent 的 thinking 启用状态(对齐 CC thinkingConfig)。
80
+
81
+ CC 对齐规则:
82
+ - plain mode: 禁用 thinking({ type: 'disabled' })
83
+ - fork mode: 继承父配置或默认启用
84
+ - coordinate mode: 继承父配置或默认启用
85
+ """
86
+ # 从父上下文获取 thinking 配置(如果有)
87
+ parent_thinking_config = getattr(parent_ctx, "thinking_config", None)
88
+ parent_thinking_enabled = getattr(parent_ctx, "thinking_enabled", None)
89
+ config = ThinkingConfig.from_subagent_mode(
90
+ self._mode,
91
+ parent_thinking_config,
92
+ parent_thinking_enabled=parent_thinking_enabled,
93
+ )
94
+ return config.enabled
95
+
96
+ def _resolve_display_mode(
97
+ self,
98
+ parent_ctx: "ToolExecutionContext",
99
+ ) -> Literal["default", "transcript"]:
100
+ """解析显示模式(对齐 CC isTranscriptMode)。
101
+
102
+ 从父上下文读取 transcript 模式标志;默认为 default。
103
+ """
104
+ if getattr(parent_ctx, "is_transcript_mode", False):
105
+ return "transcript"
106
+ return "default"
107
+
74
108
  def invoke_subagent(
75
109
  self,
76
110
  inp: "AgentToolInput",
@@ -166,6 +200,11 @@ class SubagentOrchestrator:
166
200
  inject_fork_wt = self._mode == "fork" and prepared.worktree_dir is not None
167
201
  with run_with_cwd_override(effective_cwd):
168
202
  output_dir = self._resolve_background_output_dir(runtime_ctx)
203
+
204
+ # 解析 thinking_enabled 和 display_mode
205
+ thinking_enabled = self._resolve_thinking_enabled(ctx)
206
+ display_mode = self._resolve_display_mode(ctx)
207
+
169
208
  subagent_ctx = create_subagent_context(
170
209
  parent_ctx=ctx,
171
210
  task=subagent_task,
@@ -183,6 +222,8 @@ class SubagentOrchestrator:
183
222
  fork_worktree_parent_cwd=parent_notice_cwd,
184
223
  fork_worktree_path=prepared.worktree_dir,
185
224
  available_tools=runtime_tools,
225
+ thinking_enabled=thinking_enabled,
226
+ display_mode=display_mode,
186
227
  )
187
228
  scope = propagate_subagent_tool_scope(
188
229
  parent_ctx=ctx,
@@ -359,6 +400,11 @@ class SubagentOrchestrator:
359
400
  inject_fork_wt = self._mode == "fork" and prepared.worktree_dir is not None
360
401
  with run_with_cwd_override(effective_cwd):
361
402
  output_dir = self._resolve_background_output_dir(runtime_ctx)
403
+
404
+ # 解析 thinking_enabled 和 display_mode
405
+ thinking_enabled = self._resolve_thinking_enabled(ctx)
406
+ display_mode = self._resolve_display_mode(ctx)
407
+
362
408
  subagent_ctx = create_subagent_context(
363
409
  parent_ctx=ctx,
364
410
  task=subagent_task,
@@ -376,6 +422,8 @@ class SubagentOrchestrator:
376
422
  fork_worktree_parent_cwd=parent_notice_cwd,
377
423
  fork_worktree_path=prepared.worktree_dir,
378
424
  available_tools=runtime_tools,
425
+ thinking_enabled=thinking_enabled,
426
+ display_mode=display_mode,
379
427
  )
380
428
  scope = propagate_subagent_tool_scope(
381
429
  parent_ctx=ctx,
@@ -21,6 +21,9 @@ class SubagentToolCall:
21
21
  error_message: str | None = None
22
22
  payload: str | None = None
23
23
  meta: dict[str, Any] = field(default_factory=dict)
24
+ # Phase 8: thinking 内容(对齐 CC reasoning_content)
25
+ thinking_content: str | None = None
26
+ display_mode: Literal["default", "transcript"] = "default"
24
27
 
25
28
 
26
29
  @dataclass
@@ -33,11 +36,47 @@ class SubagentExecutionTrace:
33
36
  tool_calls: list[SubagentToolCall] = field(default_factory=list)
34
37
  total_steps: int = 0
35
38
  terminal_reason: str | None = None
39
+ display_mode: Literal["default", "transcript"] = "default" # Phase 8: 显示模式
40
+ _pending_thinking_content: str | None = field(default=None, repr=False)
36
41
 
37
42
  def add_tool_call(self, call: SubagentToolCall) -> None:
38
43
  """添加工具调用记录。"""
39
44
  self.tool_calls.append(call)
40
45
  self.total_steps = max(self.total_steps, call.step)
46
+ self.apply_pending_thinking(step=call.step)
47
+
48
+ def stage_thinking_content(self, thinking_content: str) -> None:
49
+ """暂存 model 步 reasoning,待下一 tool_call 或 flush 时写入。"""
50
+ if not thinking_content:
51
+ return
52
+ self._pending_thinking_content = thinking_content
53
+
54
+ def apply_pending_thinking(self, *, step: int) -> None:
55
+ """将暂存 reasoning 写入指定 step 的 tool_call。"""
56
+ if not self._pending_thinking_content:
57
+ return
58
+ self.add_thinking_content(step=step, thinking_content=self._pending_thinking_content)
59
+ self._pending_thinking_content = None
60
+
61
+ def attach_thinking_to_last_call(self, thinking_content: str) -> None:
62
+ """将 reasoning 挂到最后一个 tool_call(无后续 tool 的最终 model 步)。"""
63
+ if not thinking_content or not self.tool_calls:
64
+ return
65
+ last = self.tool_calls[-1]
66
+ last.thinking_content = thinking_content
67
+
68
+ def add_thinking_content(self, step: int, thinking_content: str) -> None:
69
+ """添加 thinking 内容到最近的工具调用(Phase 8)。
70
+
71
+ 用于记录模型的 reasoning_content,在 transcript 模式下展示。
72
+ """
73
+ if not thinking_content:
74
+ return
75
+ # 查找对应的工具调用
76
+ for call in self.tool_calls:
77
+ if call.step == step:
78
+ call.thinking_content = thinking_content
79
+ break
41
80
 
42
81
  def update_last_status(
43
82
  self,
@@ -57,17 +96,37 @@ class SubagentExecutionTrace:
57
96
  if error_message:
58
97
  last.error_message = error_message
59
98
 
60
- def to_dict_list(self) -> list[dict[str, Any]]:
61
- """转换为字典列表,用于 JSON 序列化。"""
99
+ def to_dict_list(self, *, display_mode: Literal["default", "transcript"] | None = None) -> list[dict[str, Any]]:
100
+ """转换为字典列表,用于 JSON 序列化。
101
+
102
+ Args:
103
+ display_mode: 显示模式
104
+ - None: 使用 trace.display_mode(默认)
105
+ - "default": 仅返回摘要(step, tool_name, summary, status)
106
+ - "transcript": 返回完整信息(含 tool_input, payload, thinking_content)
107
+ """
108
+ effective_mode = display_mode if display_mode is not None else self.display_mode
109
+ if effective_mode == "transcript":
110
+ return [
111
+ {
112
+ "step": c.step,
113
+ "tool_name": c.tool_name,
114
+ "tool_input": c.tool_input,
115
+ "summary": c.summary,
116
+ "status": c.status,
117
+ "error_message": c.error_message,
118
+ "payload": c.payload,
119
+ "thinking_content": c.thinking_content,
120
+ }
121
+ for c in self.tool_calls
122
+ ]
123
+ # default 模式:仅返回摘要
62
124
  return [
63
125
  {
64
126
  "step": c.step,
65
127
  "tool_name": c.tool_name,
66
- "tool_input": c.tool_input,
67
128
  "summary": c.summary,
68
129
  "status": c.status,
69
- "error_message": c.error_message,
70
- "payload": c.payload,
71
130
  }
72
131
  for c in self.tool_calls
73
132
  ]
@@ -0,0 +1,42 @@
1
+ """loop/subagent/reasoning_extractor.py — 子 Agent 模型响应 reasoning 抽取
2
+
3
+ 职责:
4
+ 从 AIMessage 按 provider family 抽取 reasoning_text(Claude thinking / OpenAI reasoning_content)。
5
+
6
+ 链路位置:
7
+ runner._handle_chat_model_end_event → SubagentReasoningExtractor → execution_trace
8
+
9
+ 当前裁剪范围:
10
+ 仅 subagent runner 使用;不做 UI 渲染或 trace 持久化。
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from typing import Any
16
+
17
+ from langchain_agentx.provider.semantics.runtime import (
18
+ create_runtime_from_messages,
19
+ create_runtime_from_model,
20
+ )
21
+
22
+
23
+ class SubagentReasoningExtractor:
24
+ """从 model 响应抽取 reasoning 文本(委托 ProviderSemanticsRuntime)。"""
25
+
26
+ def __init__(self, model: Any | None = None) -> None:
27
+ self._model = model
28
+
29
+ def extract(self, message: Any) -> str:
30
+ if message is None:
31
+ return ""
32
+ if self._model is not None and not isinstance(self._model, str):
33
+ runtime = create_runtime_from_model(self._model)
34
+ else:
35
+ runtime = create_runtime_from_messages([message])
36
+ turn = runtime.normalize_model_end(message)
37
+ if turn is None or not turn.reasoning_text:
38
+ return ""
39
+ return str(turn.reasoning_text).strip()
40
+
41
+
42
+ __all__ = ["SubagentReasoningExtractor"]
@@ -382,10 +382,26 @@ async def _handle_chat_model_end_event(
382
382
  data: dict[str, Any],
383
383
  collected_assistant_messages: list[Any],
384
384
  total_steps: int,
385
+ trace: SubagentExecutionTrace | None = None,
386
+ model: Any | None = None,
385
387
  ) -> int:
386
388
  output = data.get("output")
387
389
  if output is not None:
388
390
  collected_assistant_messages.append(output)
391
+ if trace is not None:
392
+ from langchain_agentx.loop.subagent.reasoning_extractor import (
393
+ SubagentReasoningExtractor,
394
+ )
395
+
396
+ reasoning = SubagentReasoningExtractor(model=model).extract(output)
397
+ if reasoning:
398
+ has_tool_calls = bool(getattr(output, "tool_calls", None))
399
+ if has_tool_calls:
400
+ trace.stage_thinking_content(reasoning)
401
+ elif trace.tool_calls:
402
+ trace.attach_thinking_to_last_call(reasoning)
403
+ else:
404
+ trace.stage_thinking_content(reasoning)
389
405
  has_tool_calls = bool(output is not None and getattr(output, "tool_calls", None))
390
406
  if not has_tool_calls:
391
407
  total_steps += 1
@@ -491,6 +507,8 @@ async def _collect_subagent_events(
491
507
  data=data,
492
508
  collected_assistant_messages=collected_assistant_messages,
493
509
  total_steps=total_steps,
510
+ trace=trace,
511
+ model=getattr(ctx, "model", None),
494
512
  )
495
513
  elif event_name == "on_chain_end" and event.get("name") == "LangGraph":
496
514
  terminal_reason, child_run_id, loop_snapshot = _handle_langgraph_end_event(
@@ -621,7 +639,8 @@ async def run_subagent(
621
639
  )
622
640
  else:
623
641
  transcript = NoOpTranscriptManager()
624
- trace = SubagentExecutionTrace()
642
+ # Phase 8: 使用 ctx.display_mode 设置 trace 的显示模式
643
+ trace = SubagentExecutionTrace(display_mode=ctx.display_mode)
625
644
 
626
645
  try:
627
646
  graph = create_subagent_graph(ctx=ctx, loader=loader, model=resolved_model)
@@ -58,8 +58,11 @@ class CompatibleChatOpenAI(ChatOpenAI):
58
58
  **kwargs: Any,
59
59
  ) -> dict[str, Any]:
60
60
  """与基类一致,并为 chat/completions 的 assistant 历史补上 ``reasoning_content``。"""
61
+ kwargs.pop("thinking_enabled", None)
62
+ kwargs.pop("thinking", None)
61
63
  lc_messages = self._convert_input(input_).to_messages()
62
64
  payload = super()._get_request_payload(input_, stop=stop, **kwargs)
65
+ payload.pop("thinking", None)
63
66
  serialized = payload.get("messages")
64
67
  if not isinstance(serialized, list) or len(serialized) != len(lc_messages):
65
68
  return payload
@@ -28,6 +28,44 @@ if TYPE_CHECKING:
28
28
 
29
29
  logger = logging.getLogger(__name__)
30
30
 
31
+ _MAX_UNWRAP_DEPTH = 8
32
+
33
+
34
+ def unwrap_chat_model_for_profile(model: Any) -> Any:
35
+ """剥开 SDK/LangChain 包装,定位用于 family 识别的底层 ChatModel。
36
+
37
+ 常见链路:ToolCallDegradationCorrector → RunnableBinding → ChatAnthropic。
38
+ 仅对已知 wrapper 类型 peel,避免 Mock 等对象的自动属性误触发。
39
+ """
40
+ seen: set[int] = set()
41
+ current = model
42
+ for _ in range(_MAX_UNWRAP_DEPTH):
43
+ obj_id = id(current)
44
+ if obj_id in seen:
45
+ break
46
+ seen.add(obj_id)
47
+
48
+ cls = current.__class__
49
+ class_name = f"{cls.__module__}.{cls.__name__}"
50
+ inner = None
51
+
52
+ if (
53
+ cls.__name__ == "ToolCallDegradationCorrector"
54
+ or "tool_call_degradation_corrector" in cls.__module__
55
+ ):
56
+ candidate = getattr(current, "_llm", None)
57
+ if candidate is not None and candidate is not current:
58
+ inner = candidate
59
+ elif cls.__name__ == "RunnableBinding":
60
+ candidate = getattr(current, "bound", None)
61
+ if candidate is not None and candidate is not current:
62
+ inner = candidate
63
+
64
+ if inner is None:
65
+ break
66
+ current = inner
67
+ return current
68
+
31
69
 
32
70
  class ProviderProfileResolver:
33
71
  """Provider Profile 解析器。
@@ -54,14 +92,19 @@ class ProviderProfileResolver:
54
92
  Returns:
55
93
  ProviderProfile 实例
56
94
  """
95
+ chat_model = unwrap_chat_model_for_profile(model)
57
96
  # 获取模型类名
58
- model_class_name = f"{model.__class__.__module__}.{model.__class__.__name__}"
97
+ model_class_name = (
98
+ f"{chat_model.__class__.__module__}.{chat_model.__class__.__name__}"
99
+ )
59
100
 
60
101
  # 识别 family
61
102
  family = self._identify_family(model_class_name)
62
103
 
63
104
  # 获取模型名称(用于调试)
64
- model_name = getattr(model, "model_name", None) or getattr(model, "model", None)
105
+ model_name = getattr(chat_model, "model_name", None) or getattr(
106
+ chat_model, "model", None
107
+ )
65
108
 
66
109
  # 根据 family 构造 capabilities
67
110
  capabilities = self._get_capabilities_for_family(family)
@@ -193,4 +236,5 @@ def get_default_profile_resolver() -> ProviderProfileResolver:
193
236
  __all__ = [
194
237
  "ProviderProfileResolver",
195
238
  "get_default_profile_resolver",
239
+ "unwrap_chat_model_for_profile",
196
240
  ]
@@ -288,6 +288,25 @@ class LangChainAdapter:
288
288
  if "network_access_allowed" in configurable:
289
289
  network_access_allowed = bool(configurable.get("network_access_allowed"))
290
290
 
291
+ from langchain_agentx.loop.config.ui_display_context import UiDisplayContext
292
+
293
+ ui_display = UiDisplayContext.from_configurable(configurable)
294
+ is_transcript_mode = bool(ui_display.is_transcript_mode) if ui_display else False
295
+ ui_verbose = bool(ui_display.verbose) if ui_display else False
296
+
297
+ thinking_enabled: bool | None = None
298
+ if ui_display is not None and ui_display.thinking_enabled is not None:
299
+ thinking_enabled = ui_display.thinking_enabled
300
+ elif loop_config is not None:
301
+ if hasattr(loop_config, "get"):
302
+ raw_te = loop_config.get("thinking_enabled")
303
+ if raw_te is not None:
304
+ thinking_enabled = bool(raw_te)
305
+ else:
306
+ prompt_cfg = getattr(loop_config, "prompt", None)
307
+ if prompt_cfg is not None:
308
+ thinking_enabled = getattr(prompt_cfg, "thinking_enabled", None)
309
+
291
310
  effective_tool_flags = dict(tool_flags or {})
292
311
  if "permission_mode" in configurable:
293
312
  effective_tool_flags["permission_mode"] = configurable["permission_mode"]
@@ -343,6 +362,9 @@ class LangChainAdapter:
343
362
  capabilities=capabilities,
344
363
  network_access_allowed=network_access_allowed,
345
364
  runnable_config=runnable_config_to_pass,
365
+ is_transcript_mode=is_transcript_mode,
366
+ thinking_enabled=thinking_enabled,
367
+ ui_verbose=ui_verbose,
346
368
  )
347
369
 
348
370
  def apply_pipeline_side_effects_immediate(
@@ -143,6 +143,13 @@ class ToolExecutionContext:
143
143
  session_hint_drafts: list[Any] = field(default_factory=list)
144
144
  """defer 模式下由 ToolStateBridge 收集的 SessionHintDraft(单 call 局部)。"""
145
145
 
146
+ # UI 展示意图(CLI → SDK;对齐 CC verbose / isTranscriptMode)
147
+ is_transcript_mode: bool = False
148
+ thinking_enabled: bool | None = None
149
+ """父 loop PromptConfig.thinking_enabled;fork subagent 继承用。"""
150
+ ui_verbose: bool = False
151
+ """宿主 verbose 模式(主 Agent thinking 展示策略,供 CLI 投影层读取)。"""
152
+
146
153
  def persist_permission_updates(
147
154
  self,
148
155
  updates: Sequence["PermissionUpdate"],
@@ -389,11 +389,14 @@ class AgentRuntimeTool(RuntimeTool):
389
389
  ) -> dict[str, Any] | None:
390
390
  """out-of-band:子 agent 状态摘要与执行轨迹(对位 CC AgentTool UI)。
391
391
 
392
+ Phase 7/8: 根据 display_mode 过滤内容
393
+ - transcript 模式:返回完整 tool_calls(含 tool_input, payload, thinking_content)
394
+ - default 模式:返回摘要(仅 step, tool_name, summary, status)
395
+
392
396
  返回结构包含:
393
397
  - subagent_type, status, total_steps, terminal_reason, agent_id, child_session_id
394
- - tool_calls: 完整工具调用列表(来自 SubagentExecutionTrace.to_dict_list())
398
+ - tool_calls: 工具调用列表(根据 display_mode 过滤)
395
399
  """
396
- _ = ctx
397
400
  inp = AgentToolInput.model_validate(data)
398
401
  out = result if isinstance(result, AgentToolOutput) else AgentToolOutput.model_validate(result)
399
402
 
@@ -407,10 +410,23 @@ class AgentRuntimeTool(RuntimeTool):
407
410
  **_agent_termination_meta(out),
408
411
  }
409
412
 
410
- # 提取 execution_trace 中的 tool_calls
413
+ # Phase 7/8: 提取 execution_trace 中的 tool_calls,由 DisplayProjector 按 display_mode 投影
411
414
  if out.execution_trace is not None:
415
+ from langchain_agentx.loop.subagent.display_projector import SubagentDisplayProjector
412
416
  from langchain_agentx.loop.subagent.progress import SubagentExecutionTrace
417
+
413
418
  if isinstance(out.execution_trace, SubagentExecutionTrace):
414
- display_data["tool_calls"] = out.execution_trace.to_dict_list()
419
+ ctx_mode = getattr(ctx, "is_transcript_mode", False)
420
+ ctx_display: Literal["default", "transcript"] = (
421
+ "transcript" if ctx_mode else "default"
422
+ )
423
+ display_mode = SubagentDisplayProjector.resolve_display_mode(
424
+ out.execution_trace,
425
+ ctx_display_mode=ctx_display,
426
+ )
427
+ display_data["tool_calls"] = SubagentDisplayProjector.project_tool_calls(
428
+ out.execution_trace,
429
+ display_mode=display_mode,
430
+ )
415
431
 
416
432
  return display_data
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langchain-agentx-python
3
- Version: 1.2.2
3
+ Version: 1.2.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=gLxjoC92OvVi3mha5vefLza8Zsq5gQWFey0SROZ93nQ,1678
1
+ langchain_agentx/__init__.py,sha256=h3W5rAgNSkziLvbazQZL4kQJHc87DVInXdfhUid5RsY,1678
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
@@ -30,12 +30,14 @@ langchain_agentx/loop/loop_abort.py,sha256=hcAWC4pVkGgMZx4qlzTzP6rKpPMn5so4YXQ7a
30
30
  langchain_agentx/loop/config/__init__.py,sha256=WdRQVXuvGU4myaGOZ8guFFvUb66jfsAIp9DLANJGieg,1083
31
31
  langchain_agentx/loop/config/agent_config.py,sha256=tOnAHFor6dkle3FvUOVx0YsmiYVTH11UrWSyTmOLV0c,3100
32
32
  langchain_agentx/loop/config/interaction_profile.py,sha256=UWrlI3aTWjYRq1mDeXL-xL-iCrQU-bXDXhETP6q9icY,10020
33
- langchain_agentx/loop/config/loop_config.py,sha256=yvJmRPlufW-yLAVPEO1ZL9lgEctMSe5IBw1TzlnEfX8,14127
33
+ langchain_agentx/loop/config/loop_config.py,sha256=fiQ68EIqGY9NQMdCjCzkBcFWGGy_kutGOjFekl2mxno,14270
34
34
  langchain_agentx/loop/config/loop_runtime_overlay.py,sha256=70FDSWs9b-Y5tZ8O3D_7PricJa8mxpy0NCDpA6wbxCo,2242
35
35
  langchain_agentx/loop/config/model_context_resolver.py,sha256=o9RR0Vnu07TD4Y3V8jk5V1NfkMcPcLjE8uaaLOe22Qo,4067
36
36
  langchain_agentx/loop/config/runtime_settings.py,sha256=uKkwyxgx5u34qbjP1DFrIRt0EygRCtsH8tMN0kWA0Yo,1551
37
+ langchain_agentx/loop/config/thinking_config.py,sha256=V33oksp7XCzPKZ3gef83I2CSOlc8HSdFJQNv5sI832k,3649
37
38
  langchain_agentx/loop/config/token_estimator.py,sha256=2-Rp2Bdc5a-60D1nm88z4-sNzS25nv8hkKIfaBqE78E,4883
38
39
  langchain_agentx/loop/config/tool_execution_engine_resolver.py,sha256=6UtW_P_TmVSiz8-TmeNCPPTt73xEQye-csmXTtBZsnw,1550
40
+ langchain_agentx/loop/config/ui_display_context.py,sha256=DQMJsc-Q3_CLJIjg83dAb1CQkFMqiqMnEeQyawJGW4c,2003
39
41
  langchain_agentx/loop/context/__init__.py,sha256=RXVTFjHcH6_8q1x13Qk9ZP8RVbqZoyhlY37MXigC-DY,2240
40
42
  langchain_agentx/loop/context/blocking_guard.py,sha256=Rmt5qZdE8Zf0bt-Q6WwMSfG869772PE8w1mNPvBQRCQ,3789
41
43
  langchain_agentx/loop/context/compaction_service.py,sha256=MwAPPaT31XbzgwqpuknGBZlYBRKxwyhWXDifEnBgh2E,3725
@@ -62,7 +64,7 @@ langchain_agentx/loop/exit/terminal.py,sha256=LUqgkJYo0ySWSR-CXwaN8xAY4pjoV0n3Nv
62
64
  langchain_agentx/loop/exit/withheld_error.py,sha256=LfX3j7Rgd9VoMzlz7GOs9TPuRe7RXr_Gxweyotx3tqQ,1846
63
65
  langchain_agentx/loop/graph/__init__.py,sha256=9pUUqn7G87n3lV45iYIU24j0wcTHyCD--SSdtv3urh4,136
64
66
  langchain_agentx/loop/graph/builtin_loop_control.py,sha256=jagBvSo8fj6Yjl95rkp5A0W8RgyVf4P-EXMmGweURl8,7184
65
- langchain_agentx/loop/graph/factory.py,sha256=YD8MKtVr_ut0MIitSKpgCmgelsyzu9J-5CRd9lShP10,91503
67
+ langchain_agentx/loop/graph/factory.py,sha256=xSRLX6uV1Es_nYTm-RtVs29D3SUYaj8jkudbT1_U8-k,91560
66
68
  langchain_agentx/loop/graph/graph_edges.py,sha256=YisRMKFh3-vEJmrC6JF2RGlJgltf6TtdvApv5SoywSs,43356
67
69
  langchain_agentx/loop/graph/reactive_compact_node.py,sha256=AN31reohf25zRiqdPTmFCIQ1N6VwKn1oIkRkRuGAp4k,8725
68
70
  langchain_agentx/loop/graph/runtime_tools_node.py,sha256=5iBPvHl2hOdfnRZrwtnoD4J_SzEuQKC6VQUJyPuthgA,5089
@@ -84,7 +86,7 @@ langchain_agentx/loop/hook/executors/prompt.py,sha256=oYwOk-acH-dopzfzNUEjpPdXGk
84
86
  langchain_agentx/loop/injection/__init__.py,sha256=rEiAXYqdr_Ry8mhHBu6xZKLypnyJOxcxNe6sJns1rnc,362
85
87
  langchain_agentx/loop/injection/dedup.py,sha256=5wv-Tb8HUean9C82VazVIkTkQdIZi9gewMABukiclpI,2548
86
88
  langchain_agentx/loop/model/__init__.py,sha256=8wOiwa2Yvh7QdR6ilhk4faI7_iwNT6QSEFgewJNhhOw,57
87
- langchain_agentx/loop/model/model_node.py,sha256=nyXxdK2RzCzxPdu2s2slr9eoDz9I6jaSsoKMwNQs6W4,34162
89
+ langchain_agentx/loop/model/model_node.py,sha256=4NcjP03CioxJA2wVuUREYN5s9ierLPj8RfdsaI0-vkQ,35844
88
90
  langchain_agentx/loop/model/model_nodes.py,sha256=SqcPXJu4krh6IkrR1PHOMtaZPPZ0F09PY3_dtYtBhIk,29493
89
91
  langchain_agentx/loop/model/orphan_tool_results.py,sha256=TK8zDO63NYj0f0wDlREYN0qN8lpqnWRv9TMGDMQ3Z1Y,2493
90
92
  langchain_agentx/loop/model/retrier.py,sha256=9Zfcu51QsErI2GbsLxKCz_msoH6cdc4ReQyxC1qUW9k,11086
@@ -119,16 +121,18 @@ langchain_agentx/loop/stream/transcript_gate.py,sha256=4AH3O0l8OrY_GQdqf-TOKOVS3
119
121
  langchain_agentx/loop/subagent/__init__.py,sha256=MWa1IWt7eSdJhTnPCoIpvk5NMsPN6hknghqhX5kqwnY,2477
120
122
  langchain_agentx/loop/subagent/active_run_registry.py,sha256=KurhAMDTBnRkdxNidaMUynCTRzdDy67Tu2NwJt3UC_g,4310
121
123
  langchain_agentx/loop/subagent/async_runner.py,sha256=eElKINVzPr6zFe9a4W_Vg1NckBCMdkJn2MD9ez82mCQ,7605
122
- langchain_agentx/loop/subagent/context.py,sha256=xXgutg5TdH1Ch4q1XqH5f2zLj_FGOcqoMoDriEfakOo,20196
124
+ langchain_agentx/loop/subagent/context.py,sha256=Fanqracs0D29JjnksUkHI-7afXwswlTcxCyObck9frc,20848
125
+ langchain_agentx/loop/subagent/display_projector.py,sha256=KZWCiKd-GvVY-ewCdkE4sDmBrIMmx4OICWL8XdxeBp0,1442
123
126
  langchain_agentx/loop/subagent/fork_boilerplate.py,sha256=2Uh3cwegL7V-DvtLIxjX7ik5uW5mXfY2NBzP-biREso,5005
124
127
  langchain_agentx/loop/subagent/fork_ports.py,sha256=hZATCvlYOxNVZtR3PoOVbI1GkA0KhHEyux6lUIjG5_4,1323
125
128
  langchain_agentx/loop/subagent/fork_worktree_notice.py,sha256=WKAJVxvRMJfbzRe_07Mgrm_zQIQCYx4RwsUnWSSOnkg,1389
126
129
  langchain_agentx/loop/subagent/forked_runner.py,sha256=ZEwkNlbwp1-PlJB5COHMKUu_w8EnSMLRc8s0umZ4NuM,6667
127
- langchain_agentx/loop/subagent/graph.py,sha256=vNnM9xhcXgAK2KIpwGiT88IksxEHYBnqzgzY9INIpeE,3817
128
- langchain_agentx/loop/subagent/orchestrator.py,sha256=-2t09Vj88YzFLIhhDh2qyMe7C28vQTNqog3XirlZFfo,28679
129
- langchain_agentx/loop/subagent/progress.py,sha256=ied-eQtKxpc9MnosbywofdHTsnUYMHPEbDPgd4uLHWc,3476
130
+ langchain_agentx/loop/subagent/graph.py,sha256=SoreAH0Co4daKkc0YKnzZEhNw3VzpCgAkZM1BEI5hmo,3891
131
+ langchain_agentx/loop/subagent/orchestrator.py,sha256=tFcFTS8OdRw4H5XOBLQgHaV6-llFjve-BH2_FTh1CEY,30563
132
+ langchain_agentx/loop/subagent/progress.py,sha256=5SJD8XVA5emizGaRhD192Xc9D3nYb3BlHdnVm6g19Sc,6180
130
133
  langchain_agentx/loop/subagent/prompt.py,sha256=p7RgzibNfEJdfX8nBnZGEwQLa3_EgOn4E56T9MBRIEc,1722
131
- langchain_agentx/loop/subagent/runner.py,sha256=j3lK_uxvnUoZ0dOC4p3sA7tOdL_orN4zP77sSSrXCKQ,25511
134
+ langchain_agentx/loop/subagent/reasoning_extractor.py,sha256=KrCQtBdKzsjAEfA7H5COuXzBhuGGonT2Su8IEKYlUpA,1334
135
+ langchain_agentx/loop/subagent/runner.py,sha256=LMf3ybGf637mphbVNEdPHhmUJzY95wtIGKKhdBkuvhg,26404
132
136
  langchain_agentx/loop/subagent/subagent_termination_classifier.py,sha256=ULArQeAibgy6ETSf4vRR0L6X1rsDM7-ZuLzRWQ_pmeY,3158
133
137
  langchain_agentx/loop/subagent/transcript.py,sha256=oH8n9zAL5NneZ8-wm5Jm7DQ0B0z-dgBR7KaoR-uU3B8,7182
134
138
  langchain_agentx/memory/__init__.py,sha256=Vd2ykwjYHSKWo6Tfx0CC6GJI54LBn2K1RRVo4IoDz3Q,49
@@ -218,7 +222,7 @@ langchain_agentx/plugin/registries.py,sha256=tNegcbaI3_T3GV58RgEpoFWtOMOyBiK25Qi
218
222
  langchain_agentx/plugin/types.py,sha256=GJSOR-QDmKrIv_O0xE7qxYc_nmNUlLdxM5bNVHR2_1Q,3810
219
223
  langchain_agentx/provider/__init__.py,sha256=Wd9Ci9IXMyeoYi_F8jah8q9fp4-1G5dGAhU_mZqxkFc,750
220
224
  langchain_agentx/provider/anthropic.py,sha256=BOWmlzx2kX79hJm_Kv9Z2CHwtNQJNiRFCTEK4mDRqkE,4182
221
- langchain_agentx/provider/compatible_chat_openai.py,sha256=7Ml4dZXHmv1Fg4cC9m5HLg8hyBE7TSUkYhzhAgXg1uE,3999
225
+ langchain_agentx/provider/compatible_chat_openai.py,sha256=2mSvVLov7nGjRuQ0n7UuBGtUkhz2zYedMQpTQvmHVQA,4119
222
226
  langchain_agentx/provider/env.py,sha256=bmELhixPGoJ3b0rtgEPCB512gJF2cVS00bRQfclkwD4,1040
223
227
  langchain_agentx/provider/model_profile.py,sha256=Fl-5QOISuEB0EEQL5XyB2QMQ5zZlbWO6u0EAuZiWHMY,6246
224
228
  langchain_agentx/provider/openai.py,sha256=mNPRPhxtkKRhBVnXqJD8r1Vmo22HNM-hT-Di_VNL-ng,2996
@@ -227,7 +231,7 @@ langchain_agentx/provider/semantics/answer_assembler.py,sha256=wR0fe-OqyUmK1wrZX
227
231
  langchain_agentx/provider/semantics/contracts.py,sha256=Jsw9kMt4lMPI8rYo2xB8UB5FKTOqKbPZxoerOXfE0LA,6578
228
232
  langchain_agentx/provider/semantics/finish_reason_normalizer.py,sha256=GmIHYpUtP3MSFRgbLQxlc3zuthip5Z5ZfMUZcKkDjDw,7230
229
233
  langchain_agentx/provider/semantics/message_normalizer.py,sha256=f22_eD3thaDKznCWI1uOM-ek5AE4sLX6UGq3F4Ld5-4,3521
230
- langchain_agentx/provider/semantics/profile.py,sha256=QyiWUcc6YpcC-TseUvit9-6MzJPKwlURPSMXdZ3yfsE,6876
234
+ langchain_agentx/provider/semantics/profile.py,sha256=I8W1R_VNx6J4GWbBIhBH-UgFmxpx6unlg7hCdugYFJY,8283
231
235
  langchain_agentx/provider/semantics/registry.py,sha256=wV2T74nyZSIoQi4cOAm3SkmuouRpzq2cUL66xFuM3Rs,7861
232
236
  langchain_agentx/provider/semantics/request_codec.py,sha256=cq9u3CidOmrHlQWQbdEzCGd5HuGvvHLVX1KXELbgzjg,2017
233
237
  langchain_agentx/provider/semantics/runtime.py,sha256=vbMRPK9aBsc34SeS-ZBnMAiDEND29DSjx0zUbEoCeO0,11273
@@ -345,7 +349,7 @@ langchain_agentx/task_runtime/tasks/trace_cleanup/executor.py,sha256=qez3WnzBTag
345
349
  langchain_agentx/task_runtime/tasks/trace_cleanup/scheduler.py,sha256=lqWlCqucs26fhr4M9LfgY8I0xuNDxwSLkre6XjAJDhA,6877
346
350
  langchain_agentx/tool_runtime/__init__.py,sha256=WBRUXxT-NzW37ubRueWH4UFF7b557V0atZ9nB_yxr1Y,4925
347
351
  langchain_agentx/tool_runtime/accept_edits_fast_path.py,sha256=9Tr75ED1LfHHSrtD5Z3wHxe0PBTOHF6ms_dz5g9l2zg,1820
348
- langchain_agentx/tool_runtime/adapter.py,sha256=nTG-PHgpNUU6hL6f_pkV6i_tNFWuyHM_zYfCOh3y22Q,31198
352
+ langchain_agentx/tool_runtime/adapter.py,sha256=lPgTPpn5X2QyD8C6m-m5GxbNFXzBfRntLi4-HQkcZgs,32279
349
353
  langchain_agentx/tool_runtime/base.py,sha256=Ez9W42DsaiZcWDDO8UfRKv3E7_Z6WBcABkwdAi6qTK8,21390
350
354
  langchain_agentx/tool_runtime/capabilities.py,sha256=KHwu5KLqrpPKLOTwHhnvIIs9MTmQYeuS2hAFmI_Nsy8,3837
351
355
  langchain_agentx/tool_runtime/denial_tracking.py,sha256=FOJDGk-bWR2FpEPjFK_vLa1sP8z4U5ZCF7BNgcGwNQs,8139
@@ -359,7 +363,7 @@ langchain_agentx/tool_runtime/loader.py,sha256=RrijbkWOGYqG-1tZV-4s7wyWb2GDKQ9re
359
363
  langchain_agentx/tool_runtime/loop_loader.py,sha256=qMKDEWyRAgEriAvF4iN-NqPuQhuIoDhpdk6bcGx2T0Y,7943
360
364
  langchain_agentx/tool_runtime/loop_runtime_context.py,sha256=HBZMdtKD7MpU8o7JmURFZGPTfxr2aFFlFF2nBZR_n8s,3613
361
365
  langchain_agentx/tool_runtime/messages.py,sha256=Fp-ZiLAbOQAQa8uIv-owE8PXtWyhpYSXxtzy3PVbKSw,3631
362
- langchain_agentx/tool_runtime/models.py,sha256=8IQZZq544GPnldpxppR6CgeynIK7cuEalDBYu-Y2UwQ,19791
366
+ langchain_agentx/tool_runtime/models.py,sha256=5Uk7v74dxqiPAP3OEVlmRzxbarhf4m3VEqmghLOhr-k,20153
363
367
  langchain_agentx/tool_runtime/outer_permission_resolver.py,sha256=Mffl4asUU4KrN653Xu54w_a_nLjDQS4VtpzjAGvFTlg,3405
364
368
  langchain_agentx/tool_runtime/override.py,sha256=EmHlRZxkO2cllaw_9iYKupQrA-rBsUe0HdHbOyF_a8I,9804
365
369
  langchain_agentx/tool_runtime/path_safety.py,sha256=SlqDTQioNfgdw4_KasgNB9J2R7qIRYYjpTIwnLvu_TY,7962
@@ -456,7 +460,7 @@ langchain_agentx/tools/agent/models.py,sha256=jPxah6JgPt0UlZVyrAQxQeZmVUDOBV7xyl
456
460
  langchain_agentx/tools/agent/prompt.py,sha256=QQA40AfA5sEIl_LG7kn7UlUKFBOzsHSs_M8c5n-p7YU,8093
457
461
  langchain_agentx/tools/agent/prompt_scope.py,sha256=xQup3hosuN0B6TFq7jYV5SE6gzZNwR6BOQ552dfef5I,2677
458
462
  langchain_agentx/tools/agent/scope.py,sha256=6F2ZJgSvt-gFeciyKIQxaIiW5PBW9zUeTj3P0uxqrrg,6324
459
- langchain_agentx/tools/agent/tool.py,sha256=5Q3B7astdZtHHGnsS4qcA_LprAXL7Iw5UXNSTG9hgMg,16361
463
+ langchain_agentx/tools/agent/tool.py,sha256=jHzQGFo37yMQnnadw7X-OhFERZreA6KbDf06WZ9orIU,17230
460
464
  langchain_agentx/tools/agent/built_in/__init__.py,sha256=4YUHj8nUcUOvJW9p158W_t_RBoQt8Uh7eTt0idnCTE4,657
461
465
  langchain_agentx/tools/agent/built_in/agentx_guide.py,sha256=ICEiocaH7-kSYeZJTHcpe4xEU9SYAkkcNKskTu8v1xk,2698
462
466
  langchain_agentx/tools/agent/built_in/explore.py,sha256=PQaeqRvtV645M95o2844cCj5l6h5yjvNpfYTZrcZHqU,3483
@@ -651,8 +655,8 @@ langchain_agentx/workspace/root_grant_manager.py,sha256=W3gy8HTevbERbXqIgRcjzOXO
651
655
  langchain_agentx/workspace/tool_boundary.py,sha256=UDwX6swpSLsx9HNkYuuRRiV5o7ZZG_Bru2Yn0c5kNX8,5724
652
656
  langchain_agentx/workspace/validators.py,sha256=tQt-6TOcL8Fw7Ig5ebA9S7vGWh1rby920eFW6x8Tk9E,1439
653
657
  langchain_agentx/workspace/view.py,sha256=Ip02CZNI-ZjF5k0OYT3q7RUR_auMEw83VJ6rQsaBcYU,4588
654
- langchain_agentx_python-1.2.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
655
- langchain_agentx_python-1.2.2.dist-info/METADATA,sha256=SFntj7m8EPCZwMIFq8WVSfPi55YiHnr5WHpCc87QU9M,24846
656
- langchain_agentx_python-1.2.2.dist-info/WHEEL,sha256=51RkbunBAw4BWsgaQWTpPhg4Diwp3c9P5iaLk67Hdtg,92
657
- langchain_agentx_python-1.2.2.dist-info/top_level.txt,sha256=Ge284pniNt8xea0OLk2o9o32GqVpDhOYk20fwE-0xxA,17
658
- langchain_agentx_python-1.2.2.dist-info/RECORD,,
658
+ langchain_agentx_python-1.2.3.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
659
+ langchain_agentx_python-1.2.3.dist-info/METADATA,sha256=N4tAxp5fwPKzBz1-D0n25HdwIsFUskU8RqHS3Br1SR4,24846
660
+ langchain_agentx_python-1.2.3.dist-info/WHEEL,sha256=51RkbunBAw4BWsgaQWTpPhg4Diwp3c9P5iaLk67Hdtg,92
661
+ langchain_agentx_python-1.2.3.dist-info/top_level.txt,sha256=Ge284pniNt8xea0OLk2o9o32GqVpDhOYk20fwE-0xxA,17
662
+ langchain_agentx_python-1.2.3.dist-info/RECORD,,