langchain-agentx-python 0.1__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.
Files changed (354) hide show
  1. langchain_agentx/__init__.py +46 -0
  2. langchain_agentx/command/__init__.py +28 -0
  3. langchain_agentx/command/builtin/__init__.py +25 -0
  4. langchain_agentx/command/builtin/clear.py +33 -0
  5. langchain_agentx/command/builtin/compact.py +33 -0
  6. langchain_agentx/command/builtin/memory.py +37 -0
  7. langchain_agentx/command/builtin/reload_plugins.py +42 -0
  8. langchain_agentx/command/context.py +30 -0
  9. langchain_agentx/command/dispatcher.py +183 -0
  10. langchain_agentx/command/registry.py +110 -0
  11. langchain_agentx/command/result.py +25 -0
  12. langchain_agentx/command/types.py +41 -0
  13. langchain_agentx/config/__init__.py +14 -0
  14. langchain_agentx/loop/__init__.py +47 -0
  15. langchain_agentx/loop/config/__init__.py +20 -0
  16. langchain_agentx/loop/config/agent_config.py +66 -0
  17. langchain_agentx/loop/config/agent_loop_config.py +72 -0
  18. langchain_agentx/loop/config/model_context_resolver.py +105 -0
  19. langchain_agentx/loop/config/runtime_settings.py +50 -0
  20. langchain_agentx/loop/config/token_estimator.py +133 -0
  21. langchain_agentx/loop/context/__init__.py +66 -0
  22. langchain_agentx/loop/context/blocking_guard.py +97 -0
  23. langchain_agentx/loop/context/compaction_service.py +60 -0
  24. langchain_agentx/loop/context/message_utils.py +56 -0
  25. langchain_agentx/loop/context/pipeline.py +127 -0
  26. langchain_agentx/loop/context/settings.py +103 -0
  27. langchain_agentx/loop/context/stages/__init__.py +29 -0
  28. langchain_agentx/loop/context/stages/autocompact.py +140 -0
  29. langchain_agentx/loop/context/stages/base.py +32 -0
  30. langchain_agentx/loop/context/stages/collapse.py +76 -0
  31. langchain_agentx/loop/context/stages/microcompact.py +76 -0
  32. langchain_agentx/loop/context/stages/noop.py +33 -0
  33. langchain_agentx/loop/context/stages/snip.py +71 -0
  34. langchain_agentx/loop/context/stages/tool_result_budget.py +69 -0
  35. langchain_agentx/loop/context/types.py +79 -0
  36. langchain_agentx/loop/exit/__init__.py +1 -0
  37. langchain_agentx/loop/exit/exit_logic.py +320 -0
  38. langchain_agentx/loop/exit/reason_codes.py +39 -0
  39. langchain_agentx/loop/graph/__init__.py +5 -0
  40. langchain_agentx/loop/graph/builtin_loop_control.py +197 -0
  41. langchain_agentx/loop/graph/factory.py +1409 -0
  42. langchain_agentx/loop/graph/graph_edges.py +820 -0
  43. langchain_agentx/loop/hook/__init__.py +48 -0
  44. langchain_agentx/loop/hook/async_hook_runner.py +62 -0
  45. langchain_agentx/loop/hook/config.py +280 -0
  46. langchain_agentx/loop/hook/engine.py +321 -0
  47. langchain_agentx/loop/hook/executors/__init__.py +9 -0
  48. langchain_agentx/loop/hook/executors/agent.py +107 -0
  49. langchain_agentx/loop/hook/executors/command.py +230 -0
  50. langchain_agentx/loop/hook/executors/http.py +114 -0
  51. langchain_agentx/loop/hook/executors/prompt.py +92 -0
  52. langchain_agentx/loop/hook/graph_wiring.py +134 -0
  53. langchain_agentx/loop/hook/registry.py +262 -0
  54. langchain_agentx/loop/hook/trust.py +43 -0
  55. langchain_agentx/loop/hook/types.py +110 -0
  56. langchain_agentx/loop/injection/__init__.py +13 -0
  57. langchain_agentx/loop/injection/dedup.py +74 -0
  58. langchain_agentx/loop/loop_abort.py +36 -0
  59. langchain_agentx/loop/model/__init__.py +1 -0
  60. langchain_agentx/loop/model/model_node.py +648 -0
  61. langchain_agentx/loop/model/model_nodes.py +661 -0
  62. langchain_agentx/loop/model/orphan_tool_results.py +38 -0
  63. langchain_agentx/loop/model/retrier.py +307 -0
  64. langchain_agentx/loop/model/retry_bridge.py +58 -0
  65. langchain_agentx/loop/model/retry_events.py +35 -0
  66. langchain_agentx/loop/model/retry_policy.py +56 -0
  67. langchain_agentx/loop/model/schema_and_format.py +153 -0
  68. langchain_agentx/loop/model/tool_and_model_binding.py +227 -0
  69. langchain_agentx/loop/model/tool_call_degradation_corrector.py +443 -0
  70. langchain_agentx/loop/model/tool_transcript_guard.py +225 -0
  71. langchain_agentx/loop/prompt/__init__.py +95 -0
  72. langchain_agentx/loop/prompt/builder.py +61 -0
  73. langchain_agentx/loop/prompt/builtin.py +218 -0
  74. langchain_agentx/loop/prompt/compact.py +408 -0
  75. langchain_agentx/loop/prompt/sections.py +120 -0
  76. langchain_agentx/loop/runtime/__init__.py +19 -0
  77. langchain_agentx/loop/runtime/context.py +34 -0
  78. langchain_agentx/loop/runtime/context_factory.py +107 -0
  79. langchain_agentx/loop/runtime/subagent_execution_paths.py +68 -0
  80. langchain_agentx/loop/subagent/__init__.py +53 -0
  81. langchain_agentx/loop/subagent/async_runner.py +215 -0
  82. langchain_agentx/loop/subagent/context.py +209 -0
  83. langchain_agentx/loop/subagent/fork_worktree_notice.py +25 -0
  84. langchain_agentx/loop/subagent/graph.py +72 -0
  85. langchain_agentx/loop/subagent/orchestrator.py +391 -0
  86. langchain_agentx/loop/subagent/progress.py +30 -0
  87. langchain_agentx/loop/subagent/prompt.py +52 -0
  88. langchain_agentx/loop/subagent/runner.py +504 -0
  89. langchain_agentx/loop/subagent/transcript.py +172 -0
  90. langchain_agentx/memory/__init__.py +2 -0
  91. langchain_agentx/memory/instruction/__init__.py +12 -0
  92. langchain_agentx/memory/instruction/loader.py +325 -0
  93. langchain_agentx/memory/instruction/resolver.py +24 -0
  94. langchain_agentx/memory/instruction/runtime.py +83 -0
  95. langchain_agentx/memory/instruction/sections.py +83 -0
  96. langchain_agentx/memory/instruction/types.py +59 -0
  97. langchain_agentx/memory/memdir/__init__.py +77 -0
  98. langchain_agentx/memory/memdir/age.py +36 -0
  99. langchain_agentx/memory/memdir/agent_memory.py +380 -0
  100. langchain_agentx/memory/memdir/extractor.py +309 -0
  101. langchain_agentx/memory/memdir/loader.py +187 -0
  102. langchain_agentx/memory/memdir/paths.py +63 -0
  103. langchain_agentx/memory/memdir/recall.py +45 -0
  104. langchain_agentx/memory/memdir/runtime.py +43 -0
  105. langchain_agentx/memory/memdir/scan.py +135 -0
  106. langchain_agentx/memory/memdir/types.py +104 -0
  107. langchain_agentx/memory/session/__init__.py +76 -0
  108. langchain_agentx/memory/session/compact_bridge.py +208 -0
  109. langchain_agentx/memory/session/prompts.py +172 -0
  110. langchain_agentx/memory/session/session_memory.py +282 -0
  111. langchain_agentx/observability/__init__.py +67 -0
  112. langchain_agentx/observability/evaluation/__init__.py +17 -0
  113. langchain_agentx/observability/evaluation/checkers/__init__.py +18 -0
  114. langchain_agentx/observability/evaluation/checkers/base.py +34 -0
  115. langchain_agentx/observability/evaluation/checkers/compaction.py +38 -0
  116. langchain_agentx/observability/evaluation/checkers/degradation.py +50 -0
  117. langchain_agentx/observability/evaluation/checkers/exit_quality.py +42 -0
  118. langchain_agentx/observability/evaluation/checkers/session_memory.py +45 -0
  119. langchain_agentx/observability/evaluation/checkers/tool_behavior.py +53 -0
  120. langchain_agentx/observability/evaluation/retention_scheduler.py +67 -0
  121. langchain_agentx/observability/evaluation/service.py +102 -0
  122. langchain_agentx/observability/evaluation/state.py +32 -0
  123. langchain_agentx/observability/evaluation/store.py +258 -0
  124. langchain_agentx/observability/events/__init__.py +15 -0
  125. langchain_agentx/observability/events/langchain_agentx_event_adapter.py +832 -0
  126. langchain_agentx/observability/logging/__init__.py +15 -0
  127. langchain_agentx/observability/logging/debug_burst.py +95 -0
  128. langchain_agentx/observability/logging/logging_config.py +178 -0
  129. langchain_agentx/observability/logging/logging_contract.py +65 -0
  130. langchain_agentx/observability/replay/__init__.py +35 -0
  131. langchain_agentx/observability/replay/cli.py +91 -0
  132. langchain_agentx/observability/replay/service.py +83 -0
  133. langchain_agentx/observability/replay/store.py +278 -0
  134. langchain_agentx/observability/replay/ui.py +47 -0
  135. langchain_agentx/observability/trace/__init__.py +25 -0
  136. langchain_agentx/observability/trace/collector.py +560 -0
  137. langchain_agentx/observability/trace/event_emitter.py +183 -0
  138. langchain_agentx/observability/trace/hook_event_emitter.py +49 -0
  139. langchain_agentx/observability/trace/models.py +144 -0
  140. langchain_agentx/observability/trace/sqlite_store.py +873 -0
  141. langchain_agentx/observability/trace/trace_callback.py +295 -0
  142. langchain_agentx/observability/trace/trace_lifecycle_collector.py +114 -0
  143. langchain_agentx/plugin/__init__.py +26 -0
  144. langchain_agentx/plugin/builtin.py +53 -0
  145. langchain_agentx/plugin/config.py +113 -0
  146. langchain_agentx/plugin/loader.py +386 -0
  147. langchain_agentx/plugin/manifest.py +154 -0
  148. langchain_agentx/plugin/registries.py +211 -0
  149. langchain_agentx/plugin/types.py +142 -0
  150. langchain_agentx/provider/__init__.py +27 -0
  151. langchain_agentx/provider/anthropic.py +121 -0
  152. langchain_agentx/provider/compatible_chat_openai.py +86 -0
  153. langchain_agentx/provider/env.py +45 -0
  154. langchain_agentx/provider/model_profile.py +156 -0
  155. langchain_agentx/provider/openai.py +89 -0
  156. langchain_agentx/session/__init__.py +17 -0
  157. langchain_agentx/session/agent_session.py +320 -0
  158. langchain_agentx/session/conversation_factory.py +87 -0
  159. langchain_agentx/session/conversation_recovery.py +156 -0
  160. langchain_agentx/session/conversation_session.py +198 -0
  161. langchain_agentx/session/factory.py +143 -0
  162. langchain_agentx/session/protocol.py +25 -0
  163. langchain_agentx/task_runtime/__init__.py +113 -0
  164. langchain_agentx/task_runtime/core/__init__.py +51 -0
  165. langchain_agentx/task_runtime/core/ids.py +33 -0
  166. langchain_agentx/task_runtime/core/interfaces.py +115 -0
  167. langchain_agentx/task_runtime/core/notification_priority.py +19 -0
  168. langchain_agentx/task_runtime/core/types.py +136 -0
  169. langchain_agentx/task_runtime/integrations/__init__.py +33 -0
  170. langchain_agentx/task_runtime/integrations/loop_adapter.py +91 -0
  171. langchain_agentx/task_runtime/integrations/loop_integration.py +61 -0
  172. langchain_agentx/task_runtime/integrations/prefetch_providers.py +108 -0
  173. langchain_agentx/task_runtime/integrations/provider_factory.py +103 -0
  174. langchain_agentx/task_runtime/integrations/queued_command_provider.py +184 -0
  175. langchain_agentx/task_runtime/integrations/sqlite_queued_command_provider.py +338 -0
  176. langchain_agentx/task_runtime/integrations/tool_use_summary_provider.py +254 -0
  177. langchain_agentx/task_runtime/orchestrator/__init__.py +5 -0
  178. langchain_agentx/task_runtime/orchestrator/runtime.py +386 -0
  179. langchain_agentx/task_runtime/output/__init__.py +5 -0
  180. langchain_agentx/task_runtime/output/sink.py +64 -0
  181. langchain_agentx/task_runtime/policy/__init__.py +11 -0
  182. langchain_agentx/task_runtime/policy/withhold_visibility.py +32 -0
  183. langchain_agentx/task_runtime/queue/__init__.py +5 -0
  184. langchain_agentx/task_runtime/queue/in_memory.py +55 -0
  185. langchain_agentx/task_runtime/skill_prefetch/__init__.py +4 -0
  186. langchain_agentx/task_runtime/skill_prefetch/attachments.py +46 -0
  187. langchain_agentx/task_runtime/skill_prefetch/models.py +37 -0
  188. langchain_agentx/task_runtime/skill_prefetch/provider.py +344 -0
  189. langchain_agentx/task_runtime/store/__init__.py +6 -0
  190. langchain_agentx/task_runtime/store/in_memory.py +81 -0
  191. langchain_agentx/task_runtime/store/sqlite_store.py +281 -0
  192. langchain_agentx/task_runtime/tasks/__init__.py +76 -0
  193. langchain_agentx/task_runtime/tasks/ai_analysis/__init__.py +15 -0
  194. langchain_agentx/task_runtime/tasks/ai_analysis/base.py +41 -0
  195. langchain_agentx/task_runtime/tasks/ai_analysis/evaluation.py +67 -0
  196. langchain_agentx/task_runtime/tasks/ai_analysis/registry.py +36 -0
  197. langchain_agentx/task_runtime/tasks/ai_analysis/scheduler.py +70 -0
  198. langchain_agentx/task_runtime/tasks/base/__init__.py +6 -0
  199. langchain_agentx/task_runtime/tasks/base/contracts.py +24 -0
  200. langchain_agentx/task_runtime/tasks/custom/__init__.py +7 -0
  201. langchain_agentx/task_runtime/tasks/custom/executor.py +60 -0
  202. langchain_agentx/task_runtime/tasks/custom/notification.py +7 -0
  203. langchain_agentx/task_runtime/tasks/custom/semantics.py +13 -0
  204. langchain_agentx/task_runtime/tasks/custom/spec.py +33 -0
  205. langchain_agentx/task_runtime/tasks/dream_task/__init__.py +15 -0
  206. langchain_agentx/task_runtime/tasks/dream_task/executor.py +61 -0
  207. langchain_agentx/task_runtime/tasks/dream_task/notification.py +19 -0
  208. langchain_agentx/task_runtime/tasks/dream_task/semantics.py +13 -0
  209. langchain_agentx/task_runtime/tasks/dream_task/spec.py +35 -0
  210. langchain_agentx/task_runtime/tasks/dream_task/state.py +17 -0
  211. langchain_agentx/task_runtime/tasks/in_process_teammate/__init__.py +12 -0
  212. langchain_agentx/task_runtime/tasks/in_process_teammate/executor.py +36 -0
  213. langchain_agentx/task_runtime/tasks/in_process_teammate/notification.py +25 -0
  214. langchain_agentx/task_runtime/tasks/in_process_teammate/semantics.py +13 -0
  215. langchain_agentx/task_runtime/tasks/in_process_teammate/spec.py +63 -0
  216. langchain_agentx/task_runtime/tasks/local_agent/__init__.py +14 -0
  217. langchain_agentx/task_runtime/tasks/local_agent/executor.py +33 -0
  218. langchain_agentx/task_runtime/tasks/local_agent/notification.py +21 -0
  219. langchain_agentx/task_runtime/tasks/local_agent/runner.py +43 -0
  220. langchain_agentx/task_runtime/tasks/local_agent/semantics.py +13 -0
  221. langchain_agentx/task_runtime/tasks/local_agent/spec.py +31 -0
  222. langchain_agentx/task_runtime/tasks/local_bash/__init__.py +13 -0
  223. langchain_agentx/task_runtime/tasks/local_bash/executor.py +95 -0
  224. langchain_agentx/task_runtime/tasks/local_bash/notification.py +22 -0
  225. langchain_agentx/task_runtime/tasks/local_bash/semantics.py +13 -0
  226. langchain_agentx/task_runtime/tasks/local_bash/spec.py +55 -0
  227. langchain_agentx/task_runtime/tasks/remote_agent/__init__.py +19 -0
  228. langchain_agentx/task_runtime/tasks/remote_agent/backend.py +76 -0
  229. langchain_agentx/task_runtime/tasks/remote_agent/executor.py +37 -0
  230. langchain_agentx/task_runtime/tasks/remote_agent/notification.py +22 -0
  231. langchain_agentx/task_runtime/tasks/remote_agent/semantics.py +13 -0
  232. langchain_agentx/task_runtime/tasks/remote_agent/spec.py +34 -0
  233. langchain_agentx/task_runtime/tasks/trace_cleanup/__init__.py +19 -0
  234. langchain_agentx/task_runtime/tasks/trace_cleanup/bootstrap.py +95 -0
  235. langchain_agentx/task_runtime/tasks/trace_cleanup/executor.py +66 -0
  236. langchain_agentx/task_runtime/tasks/trace_cleanup/scheduler.py +169 -0
  237. langchain_agentx/tool_runtime/__init__.py +90 -0
  238. langchain_agentx/tool_runtime/adapter.py +365 -0
  239. langchain_agentx/tool_runtime/base.py +319 -0
  240. langchain_agentx/tool_runtime/errors.py +190 -0
  241. langchain_agentx/tool_runtime/identical_call_cache.py +110 -0
  242. langchain_agentx/tool_runtime/loader.py +195 -0
  243. langchain_agentx/tool_runtime/models.py +260 -0
  244. langchain_agentx/tool_runtime/permission_context.py +78 -0
  245. langchain_agentx/tool_runtime/pipeline.py +621 -0
  246. langchain_agentx/tool_runtime/policy.py +447 -0
  247. langchain_agentx/tool_runtime/registry.py +81 -0
  248. langchain_agentx/tool_runtime/resolvers/__init__.py +27 -0
  249. langchain_agentx/tool_runtime/resolvers/agent_session.py +125 -0
  250. langchain_agentx/tool_runtime/resolvers/background.py +32 -0
  251. langchain_agentx/tool_runtime/resolvers/base.py +20 -0
  252. langchain_agentx/tool_runtime/resolvers/conversation.py +22 -0
  253. langchain_agentx/tool_runtime/resolvers/workflow.py +73 -0
  254. langchain_agentx/tool_runtime/session_store.py +132 -0
  255. langchain_agentx/tool_runtime/smoke_test_runtime.py +294 -0
  256. langchain_agentx/tool_runtime/state_bridge.py +164 -0
  257. langchain_agentx/tools/__init__.py +26 -0
  258. langchain_agentx/tools/agent/__init__.py +9 -0
  259. langchain_agentx/tools/agent/backend.py +53 -0
  260. langchain_agentx/tools/agent/built_in/__init__.py +19 -0
  261. langchain_agentx/tools/agent/built_in/agentx_guide.py +65 -0
  262. langchain_agentx/tools/agent/built_in/explore.py +80 -0
  263. langchain_agentx/tools/agent/built_in/general.py +57 -0
  264. langchain_agentx/tools/agent/built_in/plan.py +89 -0
  265. langchain_agentx/tools/agent/built_in/statusline_setup.py +64 -0
  266. langchain_agentx/tools/agent/built_in/verification.py +120 -0
  267. langchain_agentx/tools/agent/builtin_subagent_loader.py +89 -0
  268. langchain_agentx/tools/agent/cwd_resolution.py +119 -0
  269. langchain_agentx/tools/agent/limits.py +26 -0
  270. langchain_agentx/tools/agent/loader.py +270 -0
  271. langchain_agentx/tools/agent/models.py +85 -0
  272. langchain_agentx/tools/agent/prompt.py +120 -0
  273. langchain_agentx/tools/agent/registry/__init__.py +18 -0
  274. langchain_agentx/tools/agent/registry/config.py +29 -0
  275. langchain_agentx/tools/agent/registry/registry.py +47 -0
  276. langchain_agentx/tools/agent/scope.py +137 -0
  277. langchain_agentx/tools/agent/tool.py +256 -0
  278. langchain_agentx/tools/bash/__init__.py +9 -0
  279. langchain_agentx/tools/bash/ast_security.py +571 -0
  280. langchain_agentx/tools/bash/backend.py +1447 -0
  281. langchain_agentx/tools/bash/bash_hardening.py +734 -0
  282. langchain_agentx/tools/bash/bash_runtime_contract.py +41 -0
  283. langchain_agentx/tools/bash/cwd_reporter.py +95 -0
  284. langchain_agentx/tools/bash/limits.py +71 -0
  285. langchain_agentx/tools/bash/mode_validation.py +282 -0
  286. langchain_agentx/tools/bash/models.py +131 -0
  287. langchain_agentx/tools/bash/observability.py +148 -0
  288. langchain_agentx/tools/bash/output_utils.py +200 -0
  289. langchain_agentx/tools/bash/path_security.py +2429 -0
  290. langchain_agentx/tools/bash/prompt.py +68 -0
  291. langchain_agentx/tools/bash/read_only_validation.py +589 -0
  292. langchain_agentx/tools/bash/result_presenter.py +324 -0
  293. langchain_agentx/tools/bash/sandbox_decision.py +133 -0
  294. langchain_agentx/tools/bash/security.py +311 -0
  295. langchain_agentx/tools/bash/sed_edit_parser.py +243 -0
  296. langchain_agentx/tools/bash/sed_validation.py +163 -0
  297. langchain_agentx/tools/bash/semantics.py +111 -0
  298. langchain_agentx/tools/bash/session_manager.py +205 -0
  299. langchain_agentx/tools/bash/session_runtime.py +290 -0
  300. langchain_agentx/tools/bash/shell_locator.py +191 -0
  301. langchain_agentx/tools/bash/task_runtime.py +91 -0
  302. langchain_agentx/tools/bash/tool.py +939 -0
  303. langchain_agentx/tools/bash/windows_shell_quoting.py +45 -0
  304. langchain_agentx/tools/glob/__init__.py +9 -0
  305. langchain_agentx/tools/glob/models.py +57 -0
  306. langchain_agentx/tools/glob/pagination.py +30 -0
  307. langchain_agentx/tools/glob/prompt.py +24 -0
  308. langchain_agentx/tools/glob/rg_list_backend.py +139 -0
  309. langchain_agentx/tools/glob/rg_pattern.py +44 -0
  310. langchain_agentx/tools/glob/tool.py +327 -0
  311. langchain_agentx/tools/grep/__init__.py +7 -0
  312. langchain_agentx/tools/grep/backend.py +375 -0
  313. langchain_agentx/tools/grep/models.py +127 -0
  314. langchain_agentx/tools/grep/prompt.py +30 -0
  315. langchain_agentx/tools/grep/rg_subprocess_controller.py +114 -0
  316. langchain_agentx/tools/grep/tool.py +475 -0
  317. langchain_agentx/tools/read/__init__.py +9 -0
  318. langchain_agentx/tools/read/backend.py +415 -0
  319. langchain_agentx/tools/read/limits.py +67 -0
  320. langchain_agentx/tools/read/models.py +156 -0
  321. langchain_agentx/tools/read/prompt.py +73 -0
  322. langchain_agentx/tools/read/tool.py +494 -0
  323. langchain_agentx/tools/ripgrep_plugin_exclusions.py +137 -0
  324. langchain_agentx/tools/skill/__init__.py +4 -0
  325. langchain_agentx/tools/skill/argument_substitution.py +80 -0
  326. langchain_agentx/tools/skill/loader.py +196 -0
  327. langchain_agentx/tools/skill/models.py +88 -0
  328. langchain_agentx/tools/skill/policy.py +80 -0
  329. langchain_agentx/tools/skill/prompt.py +35 -0
  330. langchain_agentx/tools/skill/tool.py +222 -0
  331. langchain_agentx/utils/__init__.py +0 -0
  332. langchain_agentx/utils/cwd.py +124 -0
  333. langchain_agentx/utils/host_platform.py +112 -0
  334. langchain_agentx/utils/path_hierarchy.py +48 -0
  335. langchain_agentx/utils/path_user_input.py +66 -0
  336. langchain_agentx/utils/rg_executable.py +18 -0
  337. langchain_agentx/utils/subprocess_text.py +101 -0
  338. langchain_agentx/utils/temp_paths.py +77 -0
  339. langchain_agentx/utils/unc_path.py +25 -0
  340. langchain_agentx/utils/win_reserved_paths.py +51 -0
  341. langchain_agentx/workflow/__init__.py +7 -0
  342. langchain_agentx/workflow/base.py +97 -0
  343. langchain_agentx/workflow/batch.py +55 -0
  344. langchain_agentx/workflow/dag.py +54 -0
  345. langchain_agentx/workspace/__init__.py +13 -0
  346. langchain_agentx/workspace/config.py +140 -0
  347. langchain_agentx/workspace/path_key_normalizer.py +30 -0
  348. langchain_agentx/workspace/resolver.py +74 -0
  349. langchain_agentx/workspace/validators.py +41 -0
  350. langchain_agentx_python-0.1.dist-info/LICENSE +201 -0
  351. langchain_agentx_python-0.1.dist-info/METADATA +513 -0
  352. langchain_agentx_python-0.1.dist-info/RECORD +354 -0
  353. langchain_agentx_python-0.1.dist-info/WHEEL +5 -0
  354. langchain_agentx_python-0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,324 @@
1
+ """
2
+ tools/bash/result_presenter.py — BashRuntimeTool 模块5:结果展示协作者
3
+
4
+ 职责:
5
+ 统一承接 Bash 工具的结果展示语义,把 `BashToolOutput` 映射为
6
+ `ToolResultEnvelope`,避免 `tool.py` 继续堆积 background / image /
7
+ sandbox / no-output 等展示分支。
8
+
9
+ 在整体链路中的位置:
10
+ - 由 `tool.py::present()` 调用
11
+ - 依赖 `output_utils.py` 识别特殊输出形态
12
+ - 不参与命令执行、权限判断或 sandbox 决策
13
+
14
+ 当前包含:
15
+ 1. 后台任务、中断、sandbox violation 的统一 envelope 生成
16
+ 2. image data URI -> artifact 的结果映射
17
+ 3. no-output / return-code / destructive warning / sandbox hint 的展示汇总
18
+
19
+ 与 CC 对照:
20
+ 对应 CC `BashToolResultMessage.tsx` 与 `utils.ts` 中一部分“结果层”逻辑。
21
+ 当前是基础版 presenter:先把结构化结果和多模态 artifact 接口立住。
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ from typing import Any
27
+
28
+ from langchain_agentx.tool_runtime.models import ToolContentBlock, ToolHint, ToolResultEnvelope
29
+
30
+ from .models import BashToolOutput
31
+ from .output_utils import BashOutputArtifactBuilder
32
+
33
+
34
+ class BashResultPresenter:
35
+ """Bash 结果展示协作者。"""
36
+
37
+ def __init__(
38
+ self,
39
+ artifact_builder: BashOutputArtifactBuilder | None = None,
40
+ ) -> None:
41
+ self._artifact_builder = artifact_builder or BashOutputArtifactBuilder()
42
+
43
+ def present(
44
+ self,
45
+ *,
46
+ tool_name: str,
47
+ data: Any,
48
+ result: BashToolOutput,
49
+ ) -> ToolResultEnvelope:
50
+ # `data` 通常来自工具的 input_model(Pydantic BaseModel),
51
+ # 但在部分链路/测试中也可能是普通 dict。
52
+ if hasattr(data, "model_dump"):
53
+ # Pydantic v2 BaseModel
54
+ data_dict: dict[str, Any] = data.model_dump() # type: ignore[assignment]
55
+ elif isinstance(data, dict):
56
+ data_dict = data
57
+ else:
58
+ # 兜底:尽量不因展示层失败而中断工具链路
59
+ data_dict = {}
60
+
61
+ command = str(data_dict.get("command", ""))
62
+ description = data_dict.get("description")
63
+ description_text = str(description) if isinstance(description, str) else None
64
+
65
+ if result.background_task_id:
66
+ return self._present_background(tool_name=tool_name, result=result)
67
+
68
+ if result.interrupted:
69
+ return self._present_interrupted(tool_name=tool_name, result=result)
70
+
71
+ if result.sandbox_violation_message:
72
+ return self._present_sandbox_violation(
73
+ tool_name=tool_name,
74
+ command=command,
75
+ result=result,
76
+ )
77
+
78
+ image_artifact = self._artifact_builder.build_image_artifact(result.stdout)
79
+ if image_artifact is not None:
80
+ hints = self._build_hints(result)
81
+ if image_artifact.was_resized:
82
+ hints.append(
83
+ ToolHint(
84
+ message=(
85
+ "Image output was resized/downsampled before being exposed "
86
+ "to the model."
87
+ )
88
+ )
89
+ )
90
+
91
+ image_meta = {
92
+ "exit_code": result.exit_code,
93
+ "media_type": image_artifact.media_type,
94
+ "image_size_bytes": image_artifact.size_bytes,
95
+ }
96
+ if image_artifact.width is not None:
97
+ image_meta["image_width"] = image_artifact.width
98
+ if image_artifact.height is not None:
99
+ image_meta["image_height"] = image_artifact.height
100
+
101
+ summary = description_text or "Image output produced by bash command"
102
+ return ToolResultEnvelope(
103
+ status="ok",
104
+ tool_name=tool_name,
105
+ summary=summary,
106
+ payload=f"[Image output detected: {image_artifact.media_type}]",
107
+ blocks=[
108
+ ToolContentBlock(type="status", text="image_output_detected"),
109
+ ToolContentBlock(
110
+ type="image",
111
+ uri=image_artifact.artifact.uri,
112
+ media_type=image_artifact.media_type,
113
+ ),
114
+ ],
115
+ artifacts=[image_artifact.artifact],
116
+ hints=hints or None,
117
+ meta=self._attach_observability(image_meta, result),
118
+ )
119
+
120
+ if result.no_output_expected and not result.stdout.strip():
121
+ summary = description_text or f"Ran: {command[:60]}"
122
+ hints = self._build_hints(result)
123
+ return ToolResultEnvelope(
124
+ status="ok",
125
+ tool_name=tool_name,
126
+ summary=summary,
127
+ payload="Done",
128
+ blocks=[ToolContentBlock(type="status", text="command_completed_no_output")],
129
+ hints=hints or None,
130
+ meta=self._attach_observability({
131
+ "exit_code": result.exit_code,
132
+ "task_mode": result.task_mode,
133
+ "task_status": result.task_status,
134
+ "task_exit_code": result.task_exit_code,
135
+ }, result),
136
+ )
137
+
138
+ summary = description_text or f"Ran: {command[:60]}"
139
+ payload = result.stdout or "(No output)"
140
+ hints = self._build_hints(result)
141
+ if result.output_truncated and result.overflow_file:
142
+ return ToolResultEnvelope(
143
+ status="ok",
144
+ tool_name=tool_name,
145
+ summary=summary + " (stdout truncated; full output spilled to file)",
146
+ payload=(
147
+ f"{payload}\n\n"
148
+ f"[Full output: {result.overflow_file} — use Read tool with this path]"
149
+ ),
150
+ blocks=[
151
+ ToolContentBlock(
152
+ type="status",
153
+ text="stdout_truncated",
154
+ meta={"overflow_file": result.overflow_file},
155
+ ),
156
+ ToolContentBlock(
157
+ type="reference",
158
+ text="full_stdout",
159
+ uri=result.overflow_file,
160
+ ),
161
+ ToolContentBlock(type="text", text=payload),
162
+ ],
163
+ hints=hints or None,
164
+ truncated=True,
165
+ overflow_file=result.overflow_file,
166
+ meta=self._attach_observability({
167
+ "exit_code": result.exit_code,
168
+ "task_mode": result.task_mode,
169
+ "task_status": result.task_status,
170
+ "task_exit_code": result.task_exit_code,
171
+ }, result),
172
+ )
173
+ return ToolResultEnvelope(
174
+ status="ok",
175
+ tool_name=tool_name,
176
+ summary=summary,
177
+ payload=payload,
178
+ blocks=[
179
+ ToolContentBlock(
180
+ type="status",
181
+ text=f"task:{result.task_status}",
182
+ meta={"task_mode": result.task_mode, "task_exit_code": result.task_exit_code},
183
+ ),
184
+ ToolContentBlock(type="text", text=payload),
185
+ ],
186
+ hints=hints or None,
187
+ meta=self._attach_observability({
188
+ "exit_code": result.exit_code,
189
+ "task_mode": result.task_mode,
190
+ "task_status": result.task_status,
191
+ "task_exit_code": result.task_exit_code,
192
+ }, result),
193
+ )
194
+
195
+ def _present_background(
196
+ self,
197
+ *,
198
+ tool_name: str,
199
+ result: BashToolOutput,
200
+ ) -> ToolResultEnvelope:
201
+ summary = f"Command submitted to background (task: {result.background_task_id})"
202
+ if result.auto_backgrounded:
203
+ summary = f"Command auto-backgrounded (task: {result.background_task_id})"
204
+ content = (
205
+ "Command is running in the background.\n"
206
+ f"Task ID: {result.background_task_id}\n"
207
+ f"Output file: {result.background_output_path}\n"
208
+ "You will be notified when it completes. "
209
+ f"To read output: use the Read tool on {result.background_output_path}"
210
+ )
211
+ hints = self._build_hints(result)
212
+ return ToolResultEnvelope(
213
+ status="ok",
214
+ tool_name=tool_name,
215
+ summary=summary,
216
+ payload=content,
217
+ blocks=[
218
+ ToolContentBlock(
219
+ type="status",
220
+ text=f"background_task:{result.task_status}",
221
+ meta={"task_id": result.background_task_id},
222
+ ),
223
+ ToolContentBlock(
224
+ type="reference",
225
+ text="background_output",
226
+ uri=result.background_output_path,
227
+ ),
228
+ ],
229
+ hints=hints or None,
230
+ meta=self._attach_observability({
231
+ "task_id": result.background_task_id,
232
+ "task_mode": result.task_mode,
233
+ "task_status": result.task_status,
234
+ "auto_backgrounded": result.auto_backgrounded,
235
+ }, result),
236
+ )
237
+
238
+ def _present_interrupted(
239
+ self,
240
+ *,
241
+ tool_name: str,
242
+ result: BashToolOutput,
243
+ ) -> ToolResultEnvelope:
244
+ content = result.stdout
245
+ if result.stdout:
246
+ content = result.stdout + "\n<error>Command was aborted before completion</error>"
247
+ else:
248
+ content = "<error>Command was aborted before completion</error>"
249
+ return ToolResultEnvelope(
250
+ status="error",
251
+ tool_name=tool_name,
252
+ summary="Command timed out or was interrupted",
253
+ payload=content,
254
+ blocks=[ToolContentBlock(type="status", text="interrupted")],
255
+ meta=self._attach_observability({"exit_code": result.exit_code}, result),
256
+ )
257
+
258
+ def _present_sandbox_violation(
259
+ self,
260
+ *,
261
+ tool_name: str,
262
+ command: str,
263
+ result: BashToolOutput,
264
+ ) -> ToolResultEnvelope:
265
+ payload = result.stdout.strip()
266
+ if payload:
267
+ payload = f"{payload}\n{result.sandbox_violation_message}"
268
+ else:
269
+ payload = result.sandbox_violation_message
270
+ return ToolResultEnvelope(
271
+ status="error",
272
+ tool_name=tool_name,
273
+ summary="Sandbox restriction prevented command execution",
274
+ payload=payload,
275
+ blocks=[ToolContentBlock(type="status", text="sandbox_violation")],
276
+ meta=self._attach_observability({"exit_code": result.exit_code, "command": command}, result),
277
+ )
278
+
279
+ def _build_hints(self, result: BashToolOutput) -> list[ToolHint]:
280
+ hints: list[ToolHint] = []
281
+
282
+ if result.return_code_interpretation:
283
+ hints.append(ToolHint(message=result.return_code_interpretation))
284
+
285
+ if result.destructive_warning:
286
+ hints.append(ToolHint(message=f"Warning: {result.destructive_warning}"))
287
+
288
+ if result.sandboxed and result.sandbox_temp_dir:
289
+ hints.append(
290
+ ToolHint(
291
+ message=(
292
+ "Command ran in sandbox mode with isolated temporary directory: "
293
+ f"{result.sandbox_temp_dir}"
294
+ )
295
+ )
296
+ )
297
+ elif result.sandbox_bypass_reason:
298
+ hints.append(
299
+ ToolHint(
300
+ message=(
301
+ "Command ran without sandbox. "
302
+ f"Reason: {result.sandbox_bypass_reason}"
303
+ )
304
+ )
305
+ )
306
+
307
+ if result.auto_backgrounded:
308
+ hints.append(
309
+ ToolHint(
310
+ message=(
311
+ "Command was automatically moved to background due to "
312
+ "long-timeout policy."
313
+ )
314
+ )
315
+ )
316
+
317
+ return hints
318
+
319
+ @staticmethod
320
+ def _attach_observability(base_meta: dict, result: BashToolOutput) -> dict:
321
+ meta = dict(base_meta)
322
+ if result.observability:
323
+ meta["observability"] = result.observability
324
+ return meta
@@ -0,0 +1,133 @@
1
+ """
2
+ tools/bash/sandbox_decision.py — BashRuntimeTool 模块4:沙箱决策层
3
+
4
+ 职责:
5
+ 在真正执行命令前,决定本次 Bash 调用是否应走 sandbox backend,
6
+ 并给出 bypass / excluded / override_not_allowed 等结构化原因。
7
+
8
+ 设计目标:
9
+ - 对齐 CC `shouldUseSandbox.ts` 的决策链,但按本工程 OOP 风格拆成独立协作者
10
+ - 让 `tool.py` 只负责编排,不在执行前散落沙箱规则
11
+ - 为后续替换成真实 OS 级沙箱后端保留稳定输入输出契约
12
+
13
+ 当前覆盖:
14
+ - sandbox enable / disable 总开关
15
+ - `dangerously_disable_sandbox` 参数
16
+ - ctx.tool_flags 注入的策略控制(允许绕过、excluded commands)
17
+ - 基于 canonical command 的 excluded pattern 匹配
18
+
19
+ 与 CC 对照:
20
+ 对应 CC `shouldUseSandbox.ts` 的基础版能力,不包含其动态配置系统和完整
21
+ SandboxManager 实现。
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import fnmatch
27
+ from dataclasses import dataclass, field
28
+
29
+ from langchain_agentx.tool_runtime.models import ToolExecutionContext
30
+
31
+ from .bash_hardening import BashCommandCanonicalizer
32
+
33
+
34
+ @dataclass(frozen=True)
35
+ class BashSandboxConfig:
36
+ enabled: bool = True
37
+ allow_unsandboxed_commands: bool = False
38
+ excluded_commands: tuple[str, ...] = ()
39
+
40
+
41
+ @dataclass(frozen=True)
42
+ class BashSandboxDecision:
43
+ use_sandbox: bool
44
+ reason: str
45
+ matched_excluded_pattern: str | None = None
46
+ override_requested: bool = False
47
+ override_allowed: bool = False
48
+
49
+
50
+ class BashSandboxDecisionEngine:
51
+ """Bash 沙箱决策协作者。"""
52
+
53
+ def __init__(
54
+ self,
55
+ config: BashSandboxConfig | None = None,
56
+ canonicalizer: BashCommandCanonicalizer | None = None,
57
+ ) -> None:
58
+ self._config = config or BashSandboxConfig()
59
+ self._canonicalizer = canonicalizer or BashCommandCanonicalizer()
60
+
61
+ def decide(
62
+ self,
63
+ *,
64
+ command: str,
65
+ dangerously_disable_sandbox: bool,
66
+ ctx: ToolExecutionContext,
67
+ ) -> BashSandboxDecision:
68
+ if not self._config.enabled:
69
+ return BashSandboxDecision(use_sandbox=False, reason="sandbox_disabled")
70
+
71
+ if not command.strip():
72
+ return BashSandboxDecision(use_sandbox=False, reason="empty_command")
73
+
74
+ matched_pattern = self._match_excluded_pattern(command, ctx)
75
+ if matched_pattern is not None:
76
+ return BashSandboxDecision(
77
+ use_sandbox=False,
78
+ reason="excluded_command",
79
+ matched_excluded_pattern=matched_pattern,
80
+ )
81
+
82
+ if dangerously_disable_sandbox:
83
+ override_allowed = self._override_allowed(ctx)
84
+ if override_allowed:
85
+ return BashSandboxDecision(
86
+ use_sandbox=False,
87
+ reason="explicit_override",
88
+ override_requested=True,
89
+ override_allowed=True,
90
+ )
91
+ return BashSandboxDecision(
92
+ use_sandbox=True,
93
+ reason="override_not_allowed",
94
+ override_requested=True,
95
+ override_allowed=False,
96
+ )
97
+
98
+ return BashSandboxDecision(use_sandbox=True, reason="sandbox_enabled")
99
+
100
+ def _match_excluded_pattern(
101
+ self,
102
+ command: str,
103
+ ctx: ToolExecutionContext,
104
+ ) -> str | None:
105
+ candidates = self._candidate_commands(command)
106
+ configured_patterns = list(self._config.excluded_commands)
107
+ configured_patterns.extend(
108
+ tuple((ctx.tool_flags or {}).get("sandbox_excluded_commands", ()))
109
+ )
110
+ for pattern in configured_patterns:
111
+ if any(self._matches_pattern(candidate, pattern) for candidate in candidates):
112
+ return pattern
113
+ return None
114
+
115
+ def _candidate_commands(self, command: str) -> list[str]:
116
+ canonical = self._canonicalizer.canonicalize(command)
117
+ candidates = [command.strip()]
118
+ if canonical and canonical not in candidates:
119
+ candidates.append(canonical)
120
+ return candidates
121
+
122
+ def _override_allowed(self, ctx: ToolExecutionContext) -> bool:
123
+ tool_flags = ctx.tool_flags or {}
124
+ return bool(
125
+ tool_flags.get("allow_dangerously_disable_sandbox")
126
+ or self._config.allow_unsandboxed_commands
127
+ )
128
+
129
+ @staticmethod
130
+ def _matches_pattern(command: str, pattern: str) -> bool:
131
+ if any(symbol in pattern for symbol in "*?[]"):
132
+ return fnmatch.fnmatch(command, pattern)
133
+ return command == pattern or command.startswith(f"{pattern} ")