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,307 @@
1
+ """
2
+ Loop model 调用重试器。
3
+
4
+ 职责:
5
+ - 以 OOP 方式编排重试循环与等待策略
6
+ - 产出对用户可见的重试事件(scheduled/heartbeat)
7
+ - 复用默认异常分类(retry_on)
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import asyncio
13
+ from dataclasses import dataclass
14
+ from typing import Awaitable, Callable, Generic, Literal, Protocol, TypeVar
15
+
16
+ from .retry_events import ModelRetryEvent
17
+ from .retry_policy import RetryDelayPolicy, RetryHeartbeatPolicy
18
+
19
+ T = TypeVar("T")
20
+ RetryScope = Literal["foreground", "background"]
21
+
22
+
23
+ @dataclass(slots=True)
24
+ class RetryContext:
25
+ scope: RetryScope = "foreground"
26
+
27
+
28
+ def default_retry_on(exc: Exception) -> bool:
29
+ """判断异常是否应该重试。排除用户取消;覆盖常见限流/连接/服务端错误。"""
30
+ if isinstance(exc, (KeyboardInterrupt, SystemExit)):
31
+ return False
32
+ try:
33
+ if isinstance(exc, asyncio.CancelledError):
34
+ return False
35
+ except Exception:
36
+ return False
37
+
38
+ status = getattr(exc, "status_code", None) or getattr(exc, "status", None)
39
+ if isinstance(status, int) and status in (429, 500, 502, 503, 504, 529):
40
+ return True
41
+
42
+ try:
43
+ from openai import APIConnectionError, InternalServerError, RateLimitError
44
+
45
+ if isinstance(exc, (RateLimitError, APIConnectionError, InternalServerError)):
46
+ return True
47
+ except ImportError:
48
+ pass
49
+
50
+ try:
51
+ import httpx
52
+
53
+ if isinstance(exc, (httpx.ConnectError, httpx.TimeoutException, httpx.RemoteProtocolError)):
54
+ return True
55
+ except ImportError:
56
+ pass
57
+
58
+ return False
59
+
60
+
61
+ def _extract_status_code(exc: Exception) -> int | None:
62
+ status = getattr(exc, "status_code", None) or getattr(exc, "status", None)
63
+ return status if isinstance(status, int) else None
64
+
65
+
66
+ class AuthRecoveryHandler(Protocol):
67
+ def recover(self, exc: Exception) -> bool: ...
68
+
69
+ async def arecover(self, exc: Exception) -> bool: ...
70
+
71
+
72
+ @dataclass(slots=True)
73
+ class RetryClassifier:
74
+ retry_on: Callable[[Exception], bool]
75
+ allow_background_529_retry: bool = False
76
+ has_auth_recovery_handler: bool = False
77
+
78
+ def should_retry(self, exc: Exception, ctx: RetryContext) -> bool:
79
+ status = _extract_status_code(exc)
80
+ if status == 529 and ctx.scope == "background" and not self.allow_background_529_retry:
81
+ return False
82
+ if status in (401, 403):
83
+ return self.has_auth_recovery_handler
84
+ if status in (408, 409):
85
+ return True
86
+ return self.retry_on(exc)
87
+
88
+ def should_attempt_auth_recovery(self, exc: Exception) -> bool:
89
+ return _extract_status_code(exc) in (401, 403)
90
+
91
+
92
+ @dataclass(slots=True)
93
+ class ModelRetryConfig:
94
+ max_retries: int = 10
95
+ initial_delay: float = 0.5
96
+ backoff_factor: float = 2.0
97
+ max_delay: float = 32.0
98
+ jitter: bool = True
99
+ heartbeat_threshold_seconds: float = 30.0
100
+ heartbeat_interval_seconds: float = 30.0
101
+ retry_on: Callable[[Exception], bool] = default_retry_on
102
+ allow_background_529_retry: bool = False
103
+ auth_recovery_handler: AuthRecoveryHandler | None = None
104
+
105
+
106
+ @dataclass(slots=True)
107
+ class RetryExecutionResult(Generic[T]):
108
+ value: T
109
+ events: list[ModelRetryEvent]
110
+
111
+
112
+ @dataclass(slots=True)
113
+ class ModelCallRetrier:
114
+ config: ModelRetryConfig
115
+
116
+ def invoke(
117
+ self,
118
+ fn: Callable[[], T],
119
+ *,
120
+ context: RetryContext | None = None,
121
+ ) -> RetryExecutionResult[T]:
122
+ events: list[ModelRetryEvent] = []
123
+ delay_policy = self._delay_policy()
124
+ hb_policy = self._heartbeat_policy()
125
+ classifier = self._classifier()
126
+ ctx = context or RetryContext()
127
+ attempt = 0
128
+ auth_recovery_attempted = False
129
+ while True:
130
+ try:
131
+ return RetryExecutionResult(value=fn(), events=events)
132
+ except Exception as exc:
133
+ if (not auth_recovery_attempted) and self._recover_auth_sync(exc, classifier):
134
+ auth_recovery_attempted = True
135
+ continue
136
+ if attempt >= self.config.max_retries or not classifier.should_retry(exc, ctx):
137
+ raise
138
+ self._sleep_before_next(
139
+ attempt=attempt,
140
+ exc=exc,
141
+ events=events,
142
+ delay_policy=delay_policy,
143
+ heartbeat_policy=hb_policy,
144
+ )
145
+ auth_recovery_attempted = False
146
+ attempt += 1
147
+
148
+ async def ainvoke(
149
+ self,
150
+ fn: Callable[[], Awaitable[T]],
151
+ *,
152
+ context: RetryContext | None = None,
153
+ ) -> RetryExecutionResult[T]:
154
+ events: list[ModelRetryEvent] = []
155
+ delay_policy = self._delay_policy()
156
+ hb_policy = self._heartbeat_policy()
157
+ classifier = self._classifier()
158
+ ctx = context or RetryContext()
159
+ attempt = 0
160
+ auth_recovery_attempted = False
161
+ while True:
162
+ try:
163
+ return RetryExecutionResult(value=await fn(), events=events)
164
+ except Exception as exc:
165
+ if (not auth_recovery_attempted) and await self._recover_auth_async(exc, classifier):
166
+ auth_recovery_attempted = True
167
+ continue
168
+ if attempt >= self.config.max_retries or not classifier.should_retry(exc, ctx):
169
+ raise
170
+ await self._asleep_before_next(
171
+ attempt=attempt,
172
+ exc=exc,
173
+ events=events,
174
+ delay_policy=delay_policy,
175
+ heartbeat_policy=hb_policy,
176
+ )
177
+ auth_recovery_attempted = False
178
+ attempt += 1
179
+
180
+ def _sleep_before_next(
181
+ self,
182
+ *,
183
+ attempt: int,
184
+ exc: Exception,
185
+ events: list[ModelRetryEvent],
186
+ delay_policy: RetryDelayPolicy,
187
+ heartbeat_policy: RetryHeartbeatPolicy,
188
+ ) -> None:
189
+ import time
190
+
191
+ delay = delay_policy.compute_delay_seconds(attempt=attempt, exc=exc)
192
+ self._record_wait_events(
193
+ events=events,
194
+ attempt=attempt,
195
+ exc=exc,
196
+ delay_seconds=delay,
197
+ heartbeat_policy=heartbeat_policy,
198
+ )
199
+ time.sleep(delay)
200
+
201
+ async def _asleep_before_next(
202
+ self,
203
+ *,
204
+ attempt: int,
205
+ exc: Exception,
206
+ events: list[ModelRetryEvent],
207
+ delay_policy: RetryDelayPolicy,
208
+ heartbeat_policy: RetryHeartbeatPolicy,
209
+ ) -> None:
210
+ delay = delay_policy.compute_delay_seconds(attempt=attempt, exc=exc)
211
+ self._record_wait_events(
212
+ events=events,
213
+ attempt=attempt,
214
+ exc=exc,
215
+ delay_seconds=delay,
216
+ heartbeat_policy=heartbeat_policy,
217
+ )
218
+ await asyncio.sleep(delay)
219
+
220
+ def _record_wait_events(
221
+ self,
222
+ *,
223
+ events: list[ModelRetryEvent],
224
+ attempt: int,
225
+ exc: Exception,
226
+ delay_seconds: float,
227
+ heartbeat_policy: RetryHeartbeatPolicy,
228
+ ) -> None:
229
+ total_ms = max(0, int(delay_seconds * 1000))
230
+ attempt_no = attempt + 1
231
+ events.append(
232
+ ModelRetryEvent(
233
+ event_type="scheduled",
234
+ retry_in_ms=total_ms,
235
+ attempt=attempt_no,
236
+ max_retries=self.config.max_retries,
237
+ error_type=type(exc).__name__,
238
+ error_message=str(exc),
239
+ )
240
+ )
241
+ if not heartbeat_policy.should_emit_heartbeat(delay_seconds):
242
+ return
243
+
244
+ interval_ms = max(1000, int(heartbeat_policy.interval_seconds * 1000))
245
+ remaining = total_ms - interval_ms
246
+ while remaining > 0:
247
+ events.append(
248
+ ModelRetryEvent(
249
+ event_type="heartbeat",
250
+ retry_in_ms=remaining,
251
+ attempt=attempt_no,
252
+ max_retries=self.config.max_retries,
253
+ error_type=type(exc).__name__,
254
+ error_message=str(exc),
255
+ )
256
+ )
257
+ remaining -= interval_ms
258
+
259
+ def _delay_policy(self) -> RetryDelayPolicy:
260
+ return RetryDelayPolicy(
261
+ initial_delay=self.config.initial_delay,
262
+ backoff_factor=self.config.backoff_factor,
263
+ max_delay=self.config.max_delay,
264
+ jitter=self.config.jitter,
265
+ )
266
+
267
+ def _heartbeat_policy(self) -> RetryHeartbeatPolicy:
268
+ return RetryHeartbeatPolicy(
269
+ threshold_seconds=self.config.heartbeat_threshold_seconds,
270
+ interval_seconds=self.config.heartbeat_interval_seconds,
271
+ )
272
+
273
+ def _classifier(self) -> RetryClassifier:
274
+ return RetryClassifier(
275
+ retry_on=self.config.retry_on,
276
+ allow_background_529_retry=self.config.allow_background_529_retry,
277
+ has_auth_recovery_handler=self.config.auth_recovery_handler is not None,
278
+ )
279
+
280
+ def _recover_auth_sync(self, exc: Exception, classifier: RetryClassifier) -> bool:
281
+ handler = self.config.auth_recovery_handler
282
+ if handler is None or not classifier.should_attempt_auth_recovery(exc):
283
+ return False
284
+ try:
285
+ return bool(handler.recover(exc))
286
+ except Exception:
287
+ return False
288
+
289
+ async def _recover_auth_async(self, exc: Exception, classifier: RetryClassifier) -> bool:
290
+ handler = self.config.auth_recovery_handler
291
+ if handler is None or not classifier.should_attempt_auth_recovery(exc):
292
+ return False
293
+ try:
294
+ return bool(await handler.arecover(exc))
295
+ except Exception:
296
+ return False
297
+
298
+
299
+ __all__ = [
300
+ "ModelRetryConfig",
301
+ "ModelCallRetrier",
302
+ "RetryContext",
303
+ "RetryClassifier",
304
+ "AuthRecoveryHandler",
305
+ "RetryExecutionResult",
306
+ "default_retry_on",
307
+ ]
@@ -0,0 +1,58 @@
1
+ """
2
+ 模型重试事件到 loop message 的桥接。
3
+
4
+ 职责:
5
+ - 将 retrier 产出的事件转为 SystemMessage
6
+ - 由 model_node 统一并入 Command(update={"messages": ...})
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import Iterable
12
+
13
+ from langchain_core.messages import SystemMessage
14
+ from langgraph.types import Command
15
+
16
+ from .retry_events import (
17
+ RETRY_EVENT_METADATA_FLAG,
18
+ RETRY_EVENT_SUBTYPE,
19
+ ModelRetryEvent,
20
+ )
21
+
22
+
23
+ def _format_retry_event_message(event: ModelRetryEvent) -> str:
24
+ seconds = max(0, int(round(event.retry_in_ms / 1000)))
25
+ if event.event_type == "heartbeat":
26
+ prefix = "Retry still pending"
27
+ else:
28
+ prefix = "Retry scheduled"
29
+ return (
30
+ f"[{prefix}] in {seconds}s "
31
+ f"(attempt {event.attempt}/{event.max_retries}) "
32
+ f"{event.error_type}: {event.error_message}"
33
+ )
34
+
35
+
36
+ def build_retry_event_commands(events: Iterable[ModelRetryEvent]) -> list[Command]:
37
+ commands: list[Command] = []
38
+ for event in events:
39
+ msg = SystemMessage(
40
+ content=_format_retry_event_message(event),
41
+ response_metadata={
42
+ RETRY_EVENT_METADATA_FLAG: True,
43
+ "subtype": RETRY_EVENT_SUBTYPE,
44
+ "event_type": event.event_type,
45
+ "retry_in_ms": event.retry_in_ms,
46
+ "attempt": event.attempt,
47
+ "max_retries": event.max_retries,
48
+ "error": {
49
+ "type": event.error_type,
50
+ "message": event.error_message,
51
+ },
52
+ },
53
+ )
54
+ commands.append(Command(update={"messages": [msg]}))
55
+ return commands
56
+
57
+
58
+ __all__ = ["build_retry_event_commands"]
@@ -0,0 +1,35 @@
1
+ """
2
+ 模型重试事件类型定义。
3
+
4
+ 职责:
5
+ - 提供 retrier 与 loop node 间的事件契约
6
+ - 约束对用户可见的重试提示字段(attempt/retry_in_ms/error)
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import dataclass
12
+ from typing import Literal
13
+
14
+
15
+ RetryEventType = Literal["scheduled", "heartbeat"]
16
+ RETRY_EVENT_METADATA_FLAG = "langchain_agentx_retry_event"
17
+ RETRY_EVENT_SUBTYPE = "api_retry"
18
+
19
+
20
+ @dataclass(slots=True)
21
+ class ModelRetryEvent:
22
+ event_type: RetryEventType
23
+ retry_in_ms: int
24
+ attempt: int
25
+ max_retries: int
26
+ error_type: str
27
+ error_message: str
28
+
29
+
30
+ __all__ = [
31
+ "ModelRetryEvent",
32
+ "RetryEventType",
33
+ "RETRY_EVENT_METADATA_FLAG",
34
+ "RETRY_EVENT_SUBTYPE",
35
+ ]
@@ -0,0 +1,56 @@
1
+ """
2
+ 模型重试策略对象。
3
+
4
+ 职责:
5
+ - 计算每次重试等待时长(优先 Retry-After)
6
+ - 管理 heartbeat 分段策略(长等待期间每 N 秒提示)
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import random
12
+ from dataclasses import dataclass
13
+
14
+
15
+ def _extract_retry_after_seconds(exc: Exception) -> int | None:
16
+ headers = getattr(exc, "headers", None)
17
+ if headers is None:
18
+ return None
19
+ retry_after = None
20
+ if hasattr(headers, "get"):
21
+ retry_after = headers.get("retry-after") or headers.get("Retry-After")
22
+ if retry_after is None:
23
+ return None
24
+ try:
25
+ return max(0, int(str(retry_after).strip()))
26
+ except Exception:
27
+ return None
28
+
29
+
30
+ @dataclass(slots=True)
31
+ class RetryDelayPolicy:
32
+ initial_delay: float = 0.5
33
+ backoff_factor: float = 2.0
34
+ max_delay: float = 32.0
35
+ jitter: bool = True
36
+
37
+ def compute_delay_seconds(self, *, attempt: int, exc: Exception) -> float:
38
+ retry_after = _extract_retry_after_seconds(exc)
39
+ if retry_after is not None:
40
+ return float(retry_after)
41
+ base = min(self.initial_delay * (self.backoff_factor ** attempt), self.max_delay)
42
+ if not self.jitter:
43
+ return base
44
+ return base * random.uniform(0.75, 1.25)
45
+
46
+
47
+ @dataclass(slots=True)
48
+ class RetryHeartbeatPolicy:
49
+ threshold_seconds: float = 30.0
50
+ interval_seconds: float = 30.0
51
+
52
+ def should_emit_heartbeat(self, delay_seconds: float) -> bool:
53
+ return delay_seconds > self.threshold_seconds
54
+
55
+
56
+ __all__ = ["RetryDelayPolicy", "RetryHeartbeatPolicy"]
@@ -0,0 +1,153 @@
1
+ """
2
+ LangChain AgentX agent 的 schema 合并与响应格式工具。
3
+
4
+ 本模块从 `factory.py` 中拆分出以下与图结构无关的纯工具逻辑:
5
+ - 基于多份 TypedDict schema 合并出 state / input / output schema
6
+ - 处理 `OmitFromSchema` / `Annotated` 等元数据,控制字段是否出现在输入或输出中
7
+ - 探测当前模型是否支持 provider 侧结构化输出(provider strategy)
8
+ - 处理 structured output 错误并决定是否重试,以及给模型的错误提示内容
9
+
10
+ 这些工具保持与 LangChain 官方语义一致,可在不同 agent 工厂中复用。
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from typing import Any, get_args, get_origin, get_type_hints
16
+
17
+ from langchain.agents.middleware.types import OmitFromSchema
18
+ from langchain.agents.structured_output import (
19
+ AutoStrategy,
20
+ MultipleStructuredOutputsError,
21
+ OutputToolBinding,
22
+ ProviderStrategy,
23
+ ProviderStrategyBinding,
24
+ ResponseFormat,
25
+ StructuredOutputError,
26
+ StructuredOutputValidationError,
27
+ ToolStrategy,
28
+ )
29
+ from langchain_core.language_models.chat_models import BaseChatModel
30
+ from langchain_core.tools import BaseTool
31
+ from typing_extensions import Annotated, NotRequired, Required, TypedDict
32
+
33
+
34
+ STRUCTURED_OUTPUT_ERROR_TEMPLATE = "Error: {error}\n Please fix your mistakes."
35
+
36
+ FALLBACK_MODELS_WITH_STRUCTURED_OUTPUT = [
37
+ # if model profile data are not available, these models are assumed to support
38
+ # structured output
39
+ "grok",
40
+ "gpt-5",
41
+ "gpt-4.1",
42
+ "gpt-4o",
43
+ "gpt-oss",
44
+ "o3-pro",
45
+ "o3-mini",
46
+ ]
47
+
48
+
49
+ def _resolve_schema(schemas: set[type], schema_name: str, omit_flag: str | None = None) -> type:
50
+ """Resolve schema by merging schemas and optionally respecting `OmitFromSchema` annotations."""
51
+ all_annotations: dict[str, Any] = {}
52
+
53
+ for schema in schemas:
54
+ hints = get_type_hints(schema, include_extras=True)
55
+
56
+ for field_name, field_type in hints.items():
57
+ should_omit = False
58
+
59
+ if omit_flag:
60
+ metadata = _extract_metadata(field_type)
61
+ for meta in metadata:
62
+ if isinstance(meta, OmitFromSchema) and getattr(meta, omit_flag) is True:
63
+ should_omit = True
64
+ break
65
+
66
+ if not should_omit:
67
+ all_annotations[field_name] = field_type
68
+
69
+ return TypedDict(schema_name, all_annotations) # type: ignore[operator]
70
+
71
+
72
+ def _extract_metadata(type_: type) -> list[Any]:
73
+ """Extract metadata from a field type, handling `Required`/`NotRequired` and `Annotated` wrappers."""
74
+ if get_origin(type_) in {Required, NotRequired}:
75
+ inner_type = get_args(type_)[0]
76
+ if get_origin(inner_type) is Annotated:
77
+ return list(get_args(inner_type)[1:])
78
+
79
+ if get_origin(type_) is Annotated:
80
+ return list(get_args(type_)[1:])
81
+
82
+ return []
83
+
84
+
85
+ def _supports_provider_strategy(
86
+ model: str | BaseChatModel, tools: list[BaseTool | dict[str, Any]] | None = None
87
+ ) -> bool:
88
+ """Check if a model supports provider-specific structured output."""
89
+ model_name: str | None = None
90
+ if isinstance(model, str):
91
+ model_name = model
92
+ elif isinstance(model, BaseChatModel):
93
+ model_name = (
94
+ getattr(model, "model_name", None)
95
+ or getattr(model, "model", None)
96
+ or getattr(model, "model_id", "")
97
+ )
98
+ model_profile = model.profile
99
+ if (
100
+ model_profile is not None
101
+ and model_profile.get("structured_output")
102
+ and not (
103
+ tools
104
+ and isinstance(model_name, str)
105
+ and "gemini" in model_name.lower()
106
+ and "gemini-3" not in model_name.lower()
107
+ )
108
+ ):
109
+ return True
110
+
111
+ return (
112
+ any(part in model_name.lower() for part in FALLBACK_MODELS_WITH_STRUCTURED_OUTPUT)
113
+ if model_name
114
+ else False
115
+ )
116
+
117
+
118
+ def _handle_structured_output_error(
119
+ exception: Exception,
120
+ response_format: ResponseFormat[Any],
121
+ ) -> tuple[bool, str]:
122
+ """Handle structured output error. Returns `(should_retry, retry_tool_message)`."""
123
+ if not isinstance(response_format, ToolStrategy):
124
+ return False, ""
125
+
126
+ handle_errors = response_format.handle_errors
127
+
128
+ if handle_errors is False:
129
+ return False, ""
130
+ if handle_errors is True:
131
+ return True, STRUCTURED_OUTPUT_ERROR_TEMPLATE.format(error=str(exception))
132
+ if isinstance(handle_errors, str):
133
+ return True, handle_errors
134
+ if isinstance(handle_errors, type):
135
+ if issubclass(handle_errors, Exception) and isinstance(exception, handle_errors):
136
+ return True, STRUCTURED_OUTPUT_ERROR_TEMPLATE.format(error=str(exception))
137
+ return False, ""
138
+ if isinstance(handle_errors, tuple):
139
+ if any(isinstance(exception, exc_type) for exc_type in handle_errors):
140
+ return True, STRUCTURED_OUTPUT_ERROR_TEMPLATE.format(error=str(exception))
141
+ return False, ""
142
+ return True, handle_errors(exception)
143
+
144
+
145
+ __all__ = [
146
+ "STRUCTURED_OUTPUT_ERROR_TEMPLATE",
147
+ "FALLBACK_MODELS_WITH_STRUCTURED_OUTPUT",
148
+ "_resolve_schema",
149
+ "_extract_metadata",
150
+ "_supports_provider_strategy",
151
+ "_handle_structured_output_error",
152
+ ]
153
+