langchain-agentx-cli 0.2.2__tar.gz → 0.3.0__tar.gz

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 (141) hide show
  1. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/PKG-INFO +2 -2
  2. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/bridge/session_bridge.py +165 -6
  3. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/state/task_store.py +63 -1
  4. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/message_events.py +122 -4
  5. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/message_list.py +240 -11
  6. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/messages/__init__.py +12 -0
  7. langchain_agentx_cli-0.3.0/langchain_agentx_cli/widgets/messages/hook_message.py +72 -0
  8. langchain_agentx_cli-0.3.0/langchain_agentx_cli/widgets/messages/stop_hook_summary.py +70 -0
  9. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/__init__.py +15 -8
  10. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/agent/widget.py +16 -1
  11. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/ask_user_question/widget.py +34 -2
  12. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/base.py +52 -3
  13. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/bash/widget.py +30 -1
  14. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/batch_edit/widget.py +19 -9
  15. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/edit/widget.py +6 -2
  16. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/glob/widget.py +6 -2
  17. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/grep/widget.py +6 -2
  18. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/helpers.py +44 -0
  19. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/read/widget.py +39 -2
  20. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/skill/widget.py +5 -1
  21. langchain_agentx_cli-0.3.0/langchain_agentx_cli/widgets/tools/user_message/widget.py +83 -0
  22. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/webfetch/widget.py +16 -2
  23. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/websearch/widget.py +11 -2
  24. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/write/widget.py +8 -2
  25. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli.egg-info/PKG-INFO +2 -2
  26. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli.egg-info/SOURCES.txt +2 -0
  27. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli.egg-info/requires.txt +1 -1
  28. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/pyproject.toml +2 -2
  29. langchain_agentx_cli-0.2.2/langchain_agentx_cli/widgets/tools/user_message/widget.py +0 -88
  30. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/LICENSE +0 -0
  31. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/README.md +0 -0
  32. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/__init__.py +0 -0
  33. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/__main__.py +0 -0
  34. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/app.py +0 -0
  35. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/bootstrap.py +0 -0
  36. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/bridge/__init__.py +0 -0
  37. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/cli.py +0 -0
  38. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/commands/__init__.py +0 -0
  39. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/commands/builtin/__init__.py +0 -0
  40. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/commands/builtin/clear.py +0 -0
  41. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/commands/builtin/compact.py +0 -0
  42. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/commands/builtin/help.py +0 -0
  43. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/commands/builtin/model.py +0 -0
  44. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/commands/builtin/quit.py +0 -0
  45. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/commands/builtin/theme.py +0 -0
  46. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/commands/parser.py +0 -0
  47. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/commands/providers/__init__.py +0 -0
  48. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/commands/providers/sdk_commands.py +0 -0
  49. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/commands/registry.py +0 -0
  50. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/completion/__init__.py +0 -0
  51. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/completion/base.py +0 -0
  52. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/completion/command_source.py +0 -0
  53. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/completion/history_source.py +0 -0
  54. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/config.py +0 -0
  55. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/history/__init__.py +0 -0
  56. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/history/store.py +0 -0
  57. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/keybindings/__init__.py +0 -0
  58. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/keybindings/bindings.py +0 -0
  59. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/llm_config.py +0 -0
  60. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/observation/__init__.py +0 -0
  61. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/observation/config.py +0 -0
  62. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/observation/observer.py +0 -0
  63. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/permissions/__init__.py +0 -0
  64. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/permissions/factory.py +0 -0
  65. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/permissions/policy.py +0 -0
  66. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/prompts/__init__.py +0 -0
  67. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/prompts/assembler.py +0 -0
  68. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/prompts/sections.py +0 -0
  69. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/prompts/system_prompt.py +0 -0
  70. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/screens/__init__.py +0 -0
  71. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/screens/repl.py +0 -0
  72. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/session_factory.py +0 -0
  73. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/session_options.py +0 -0
  74. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/state/__init__.py +0 -0
  75. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/theme/__init__.py +0 -0
  76. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/theme/colors.py +0 -0
  77. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/theme/detection.py +0 -0
  78. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/theme/manager.py +0 -0
  79. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/theme/settings.py +0 -0
  80. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/theme/system_theme.py +0 -0
  81. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/theme/themes.py +0 -0
  82. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/theme/watcher.py +0 -0
  83. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tools/__init__.py +0 -0
  84. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tools/registry.py +0 -0
  85. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/__init__.py +0 -0
  86. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/clipboard.py +0 -0
  87. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/message_selection.py +0 -0
  88. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/__init__.py +0 -0
  89. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/cache.py +0 -0
  90. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/component_manager.py +0 -0
  91. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/config.py +0 -0
  92. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/consumer.py +0 -0
  93. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/dialog.py +0 -0
  94. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/inject.py +0 -0
  95. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/models.py +0 -0
  96. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/presenters/__init__.py +0 -0
  97. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/presenters/base.py +0 -0
  98. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/presenters/bash.py +0 -0
  99. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/presenters/fallback.py +0 -0
  100. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/presenters/file.py +0 -0
  101. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/permissions/queue.py +0 -0
  102. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/tui/safe_screen.py +0 -0
  103. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/welcome.py +0 -0
  104. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/__init__.py +0 -0
  105. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/compact_progress.py +0 -0
  106. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/completion_overlay.py +0 -0
  107. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/input_area.py +0 -0
  108. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/messages/assistant_message.py +0 -0
  109. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/messages/error_message.py +0 -0
  110. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/messages/rendering.py +0 -0
  111. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/messages/thinking_message.py +0 -0
  112. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/pending_permission.py +0 -0
  113. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/permission_inline.py +0 -0
  114. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/permission_keybindings.py +0 -0
  115. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/spinner.py +0 -0
  116. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/task_panel.py +0 -0
  117. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/agent/__init__.py +0 -0
  118. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/ask_user_question/__init__.py +0 -0
  119. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/bash/__init__.py +0 -0
  120. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/batch_edit/__init__.py +0 -0
  121. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/edit/__init__.py +0 -0
  122. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/glob/__init__.py +0 -0
  123. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/grep/__init__.py +0 -0
  124. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/read/__init__.py +0 -0
  125. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/skill/__init__.py +0 -0
  126. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/user_message/__init__.py +0 -0
  127. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/webfetch/__init__.py +0 -0
  128. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/websearch/__init__.py +0 -0
  129. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli/widgets/tools/write/__init__.py +0 -0
  130. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli.egg-info/dependency_links.txt +0 -0
  131. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli.egg-info/entry_points.txt +0 -0
  132. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli.egg-info/not-zip-safe +0 -0
  133. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/langchain_agentx_cli.egg-info/top_level.txt +0 -0
  134. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/setup.cfg +0 -0
  135. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/tests/test_app_interrupt.py +0 -0
  136. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/tests/test_llm_config_chain.py +0 -0
  137. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/tests/test_repl_commands.py +0 -0
  138. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/tests/test_repl_submit_flow.py +0 -0
  139. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/tests/test_repl_ui.py +0 -0
  140. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/tests/test_smoke.py +0 -0
  141. {langchain_agentx_cli-0.2.2 → langchain_agentx_cli-0.3.0}/tests/test_welcome.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langchain-agentx-cli
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: Terminal CLI/TUI for AgentX: migrate Claude Code Ink UI, backed by langchain-agentx-python SDK.
5
5
  Author: GoodMood2008
6
6
  License: Apache-2.0
@@ -22,7 +22,7 @@ Classifier: Topic :: Software Development
22
22
  Requires-Python: >=3.11
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
- Requires-Dist: langchain-agentx-python<0.4.0,>=0.3.7
25
+ Requires-Dist: langchain-agentx-python<0.6.0,>=0.4.3
26
26
  Requires-Dist: click>=8.1
27
27
  Requires-Dist: textual>=0.79.0
28
28
  Provides-Extra: dev
@@ -46,6 +46,10 @@ from langchain_agentx_cli.widgets.messages import (
46
46
  ContextCompactedMessage,
47
47
  ContextCompactingMessage,
48
48
  ErrorMessageOccurred,
49
+ HookFinished,
50
+ HookStarted,
51
+ TaskProgress,
52
+ TaskStarted,
49
53
  ThinkingContentDelta,
50
54
  ThinkingEnded,
51
55
  ThinkingStarted,
@@ -63,9 +67,9 @@ if TYPE_CHECKING:
63
67
  MVP_ADAPTER_CONFIG: dict[str, bool] = {
64
68
  "enable_reasoning_events": True,
65
69
  "enable_step_events": False,
66
- "enable_hook_events": False,
70
+ "enable_hook_events": True, # 启用 Hook 事件
67
71
  "enable_compact_events": True,
68
- "enable_subagent_events": False,
72
+ "enable_subagent_events": True, # Phase 3: 启用子 agent 事件
69
73
  "synthesize_tool_call": True,
70
74
  }
71
75
 
@@ -112,6 +116,27 @@ class SessionBridge:
112
116
  def _post_ui(self, message: object) -> None:
113
117
  self._screen_messenger.post(message)
114
118
 
119
+ @staticmethod
120
+ def _build_fallback_text(data: dict[str, Any]) -> str:
121
+ """为未升级的 widget 提供兜底渲染文本:summary + payload。
122
+
123
+ 与 SDK envelope_to_tool_output 的语义一致(summary\\npayload),
124
+ 让仍按 event.output 字符串渲染的 widget 不需要改动即可工作。
125
+ """
126
+ summary = str(data.get("summary", ""))
127
+ payload = data.get("payload")
128
+ if payload is None or payload == "":
129
+ return summary
130
+ if isinstance(payload, str):
131
+ payload_str = payload
132
+ else:
133
+ import json
134
+ try:
135
+ payload_str = json.dumps(payload, ensure_ascii=False)
136
+ except (TypeError, ValueError):
137
+ payload_str = str(payload)
138
+ return f"{summary}\n{payload_str}" if summary else payload_str
139
+
115
140
  def submit_input(self, text: str) -> None:
116
141
  self._post_ui(UserMessage(content=text))
117
142
  self._post_ui(TurnInProgress(in_progress=True))
@@ -168,30 +193,56 @@ class SessionBridge:
168
193
  )
169
194
  case LangchainAgentEventType.TOOL_INPUT:
170
195
  tool_input = data.get("input")
196
+ tool_name = str(data.get("tool_name", ""))
171
197
  if not isinstance(tool_input, dict):
172
198
  tool_input = data.get("params") if isinstance(data.get("params"), dict) else {}
199
+ info("[BRIDGE] TOOL_INPUT tool_name=%s", tool_name)
173
200
  self._post_ui(
174
201
  ToolUseStarted(
175
- tool_name=str(data.get("tool_name", "")),
202
+ tool_name=tool_name,
176
203
  tool_input=tool_input,
177
204
  )
178
205
  )
179
206
  case LangchainAgentEventType.TOOL_CALL:
207
+ tool_name = str(data.get("tool_name", ""))
208
+ info("[BRIDGE] TOOL_CALL tool_name=%s", tool_name)
180
209
  pass
181
210
  case LangchainAgentEventType.TOOL_RESULT:
211
+ tool_name = str(data.get("tool_name", ""))
212
+ fallback_output = self._build_fallback_text(data)
213
+ info(
214
+ "[BRIDGE] TOOL_RESULT tool_name=%s summary_len=%d payload_type=%s has_display=%s",
215
+ tool_name,
216
+ len(str(data.get("summary", ""))),
217
+ type(data.get("payload")).__name__,
218
+ bool(data.get("display")),
219
+ )
182
220
  self._post_ui(
183
221
  ToolUseCompleted(
184
- tool_name=str(data.get("tool_name", "")),
185
- output=str(data.get("output", "")),
222
+ tool_name=tool_name,
223
+ output=fallback_output,
224
+ summary=str(data.get("summary", "")),
225
+ payload=data.get("payload"),
226
+ status=str(data.get("status", "ok")),
227
+ meta=data.get("meta") if isinstance(data.get("meta"), dict) else None,
228
+ display=data.get("display") if isinstance(data.get("display"), dict) else None,
229
+ truncated=bool(data.get("truncated", False)),
230
+ overflow_file=data.get("overflow_file"),
186
231
  )
187
232
  )
188
233
  case LangchainAgentEventType.TOOL_ERROR:
234
+ tool_name = str(data.get("tool_name", ""))
189
235
  error_text = str(data.get("error", ""))
190
236
  self._post_ui(
191
237
  ToolUseCompleted(
192
- tool_name=str(data.get("tool_name", "")),
238
+ tool_name=tool_name,
193
239
  output=f"Error: {error_text}",
194
240
  error=error_text or None,
241
+ summary=str(data.get("summary", "")),
242
+ payload=data.get("payload"),
243
+ status=str(data.get("status", "error")),
244
+ meta=data.get("meta") if isinstance(data.get("meta"), dict) else None,
245
+ display=data.get("display") if isinstance(data.get("display"), dict) else None,
195
246
  )
196
247
  )
197
248
  case LangchainAgentEventType.ERROR:
@@ -224,6 +275,114 @@ class SessionBridge:
224
275
  case LangchainAgentEventType.COMPACT_START:
225
276
  info("[BRIDGE] COMPACT_START — compacting...")
226
277
  pass
278
+ # Phase 3: 子 agent 工具事件(通过 adispatch_custom_event 冒泡)
279
+ case LangchainAgentEventType.SUBAGENT_TOOL_CALL:
280
+ tool_name = str(data.get("tool_name", ""))
281
+ tool_input = data.get("tool_input")
282
+ parent_tool_use_id = data.get("parent_tool_use_id")
283
+ info(
284
+ "[BRIDGE] SUBAGENT_TOOL_CALL tool=%s parent=%s",
285
+ tool_name,
286
+ parent_tool_use_id,
287
+ )
288
+ self._post_ui(
289
+ ToolUseStarted(
290
+ tool_name=tool_name,
291
+ tool_input=tool_input if isinstance(tool_input, dict) else {},
292
+ parent_tool_use_id=parent_tool_use_id,
293
+ )
294
+ )
295
+ case LangchainAgentEventType.SUBAGENT_TOOL_RESULT:
296
+ tool_name = str(data.get("tool_name", ""))
297
+ parent_tool_use_id = data.get("parent_tool_use_id")
298
+ fallback_output = self._build_fallback_text(data)
299
+ info(
300
+ "[BRIDGE] SUBAGENT_TOOL_RESULT tool=%s parent=%s summary_len=%d",
301
+ tool_name,
302
+ parent_tool_use_id,
303
+ len(str(data.get("summary", ""))),
304
+ )
305
+ self._post_ui(
306
+ ToolUseCompleted(
307
+ tool_name=tool_name,
308
+ output=fallback_output,
309
+ summary=str(data.get("summary", "")),
310
+ payload=data.get("payload"),
311
+ status=str(data.get("status", "ok")),
312
+ meta=data.get("meta") if isinstance(data.get("meta"), dict) else None,
313
+ display=data.get("display") if isinstance(data.get("display"), dict) else None,
314
+ truncated=bool(data.get("truncated", False)),
315
+ overflow_file=data.get("overflow_file"),
316
+ parent_tool_use_id=parent_tool_use_id,
317
+ )
318
+ )
319
+ case LangchainAgentEventType.HOOK_STARTED:
320
+ hook_event = str(data.get("hook_event", ""))
321
+ hook_name = str(data.get("hook_name", ""))
322
+ info("[BRIDGE] HOOK_STARTED event=%s name=%s", hook_event, hook_name)
323
+ self._post_ui(
324
+ HookStarted(
325
+ hook_event=hook_event,
326
+ hook_name=hook_name,
327
+ )
328
+ )
329
+ case LangchainAgentEventType.HOOK_FINISHED:
330
+ hook_event = str(data.get("hook_event", ""))
331
+ hook_name = str(data.get("hook_name", ""))
332
+ outcome = str(data.get("outcome", ""))
333
+ info(
334
+ "[BRIDGE] HOOK_FINISHED event=%s name=%s outcome=%s stdout_len=%d stderr_len=%d",
335
+ hook_event,
336
+ hook_name,
337
+ outcome,
338
+ len(str(data.get("combined_stdout", ""))),
339
+ len(str(data.get("combined_stderr", ""))),
340
+ )
341
+ self._post_ui(
342
+ HookFinished(
343
+ hook_event=hook_event,
344
+ hook_name=hook_name,
345
+ outcome=outcome,
346
+ stdout=data.get("combined_stdout"),
347
+ stderr=data.get("combined_stderr"),
348
+ exit_codes=data.get("exit_codes"),
349
+ combined_stdout=data.get("combined_stdout"),
350
+ combined_stderr=data.get("combined_stderr"),
351
+ )
352
+ )
353
+ case LangchainAgentEventType.TASK_STARTED:
354
+ task_id = str(data.get("task_id", ""))
355
+ task_type = str(data.get("task_type", ""))
356
+ description = str(data.get("description", ""))
357
+ tool_use_id = data.get("tool_use_id")
358
+ info("[BRIDGE] TASK_STARTED id=%s type=%s", task_id, task_type)
359
+ self._post_ui(
360
+ TaskStarted(
361
+ task_id=task_id,
362
+ task_type=task_type,
363
+ description=description,
364
+ tool_use_id=tool_use_id,
365
+ prompt=data.get("prompt"),
366
+ workflow_name=data.get("workflow_name"),
367
+ )
368
+ )
369
+ case LangchainAgentEventType.TASK_PROGRESS:
370
+ task_id = str(data.get("task_id", ""))
371
+ description = str(data.get("description", ""))
372
+ usage = data.get("usage")
373
+ last_tool_name = data.get("last_tool_name")
374
+ summary = data.get("summary")
375
+ info("[BRIDGE] TASK_PROGRESS id=%s summary=%s", task_id, summary)
376
+ self._post_ui(
377
+ TaskProgress(
378
+ task_id=task_id,
379
+ description=description,
380
+ usage=usage if isinstance(usage, dict) else None,
381
+ last_tool_name=last_tool_name,
382
+ summary=summary,
383
+ tool_use_id=data.get("tool_use_id"),
384
+ )
385
+ )
227
386
  case _:
228
387
  pass
229
388
 
@@ -19,7 +19,7 @@ from __future__ import annotations
19
19
  import time
20
20
  from dataclasses import dataclass, field
21
21
  from enum import Enum
22
- from typing import Callable
22
+ from typing import Any, Callable
23
23
 
24
24
 
25
25
  class TaskStatus(Enum):
@@ -165,6 +165,68 @@ class TaskStore:
165
165
  del self._tasks[task_id]
166
166
  self._notify()
167
167
 
168
+ def update_from_tool_result(
169
+ self,
170
+ tool_name: str,
171
+ tool_input: dict,
172
+ *,
173
+ display: dict[str, Any] | None = None,
174
+ output: str = "",
175
+ ) -> None:
176
+ """从 TOOL_RESULT 的 display 字段同步 Task 状态(D09 + SDK 双流)。"""
177
+ d = display or {}
178
+ now = time.time()
179
+
180
+ if tool_name == "TaskCreate":
181
+ if not d.get("success"):
182
+ return
183
+ task_id = str(d.get("task_id") or "").strip()
184
+ if not task_id:
185
+ return
186
+ subject = str(d.get("subject") or tool_input.get("subject", ""))
187
+ description = str(tool_input.get("description", ""))
188
+ if task_id in self._tasks:
189
+ self._tasks[task_id].subject = subject or self._tasks[task_id].subject
190
+ else:
191
+ self._tasks[task_id] = TaskEntry(
192
+ id=task_id,
193
+ subject=subject,
194
+ description=description,
195
+ status=TaskStatus.PENDING.value,
196
+ active_form=tool_input.get("activeForm"),
197
+ metadata=tool_input.get("metadata"),
198
+ )
199
+ self._notify()
200
+ return
201
+
202
+ if tool_name == "TaskUpdate":
203
+ task_id = str(d.get("task_id") or tool_input.get("taskId", "")).strip()
204
+ if not task_id or task_id not in self._tasks:
205
+ return
206
+ entry = self._tasks[task_id]
207
+ new_status = d.get("new_status")
208
+ if new_status:
209
+ if (
210
+ new_status == TaskStatus.COMPLETED.value
211
+ and entry.status != new_status
212
+ ):
213
+ entry.completed_at = now
214
+ entry.status = str(new_status)
215
+ self._notify()
216
+ return
217
+
218
+ if tool_name == "TaskGet" and d.get("found") and d.get("task_id"):
219
+ task_id = str(d["task_id"])
220
+ if task_id in self._tasks and d.get("status"):
221
+ self._tasks[task_id].status = str(d["status"])
222
+ self._notify()
223
+ return
224
+
225
+ if tool_name == "TaskList":
226
+ # 列表工具不改变单条 Task;TaskPanel 仍由 started 事件驱动
227
+ _ = output
228
+ return
229
+
168
230
  def get_sorted_tasks(self) -> list[TaskEntry]:
169
231
  """获取排序后的 Task 列表(对齐 CC 优先级)。
170
232
 
@@ -13,6 +13,8 @@ widgets/message_events.py — Textual UI 消息事件类型。
13
13
 
14
14
  from __future__ import annotations
15
15
 
16
+ from typing import Any
17
+
16
18
  from textual.message import Message
17
19
 
18
20
 
@@ -42,27 +44,63 @@ class AssistantMessageChunk(Message):
42
44
 
43
45
 
44
46
  class ToolUseStarted(Message):
45
- """工具调用开始。"""
47
+ """工具调用开始。
48
+
49
+ 属性:
50
+ parent_tool_use_id: 父级工具调用 ID(子 agent 内部工具时设置)
51
+ """
46
52
 
47
- def __init__(self, tool_name: str, tool_input: dict | None = None) -> None:
53
+ def __init__(
54
+ self,
55
+ tool_name: str,
56
+ tool_input: dict | None = None,
57
+ *,
58
+ parent_tool_use_id: str | None = None,
59
+ ) -> None:
48
60
  self.tool_name = tool_name
49
61
  self.tool_input = tool_input if tool_input is not None else {}
62
+ self.parent_tool_use_id = parent_tool_use_id
50
63
  super().__init__()
51
64
 
52
65
 
53
66
  class ToolUseCompleted(Message):
54
- """工具调用完成(含 TOOL_ERROR)。"""
67
+ """工具调用完成(含 TOOL_ERROR)。
68
+
69
+ 对齐 SDK 0.3.9 双流契约(envelope_to_event_artifact v1):
70
+ - summary/payload/status/meta/truncated/overflow_file:模型可见的结构化字段
71
+ - display:out-of-band UI 数据(如 user_message 的 message + attachments)
72
+ - output:兜底文本(summary + payload 拼接),未升级的 widget 仍用此渲染
73
+
74
+ 属性:
75
+ parent_tool_use_id: 父级工具调用 ID(子 agent 内部工具时设置)
76
+ """
55
77
 
56
78
  def __init__(
57
79
  self,
58
80
  tool_name: str,
59
- output: str,
81
+ output: str = "",
60
82
  *,
61
83
  error: str | None = None,
84
+ summary: str = "",
85
+ payload: Any = None,
86
+ status: str = "ok",
87
+ meta: dict[str, Any] | None = None,
88
+ display: dict[str, Any] | None = None,
89
+ truncated: bool = False,
90
+ overflow_file: str | None = None,
91
+ parent_tool_use_id: str | None = None,
62
92
  ) -> None:
63
93
  self.tool_name = tool_name
64
94
  self.output = output
65
95
  self.error = error
96
+ self.summary = summary
97
+ self.payload = payload
98
+ self.status = status
99
+ self.meta = meta or {}
100
+ self.display = display or {}
101
+ self.truncated = truncated
102
+ self.overflow_file = overflow_file
103
+ self.parent_tool_use_id = parent_tool_use_id
66
104
  super().__init__()
67
105
 
68
106
 
@@ -174,3 +212,83 @@ class CompactFinished(Message):
174
212
  self.before = before
175
213
  self.after = after
176
214
  super().__init__()
215
+
216
+
217
+ class HookStarted(Message):
218
+ """Hook 执行开始。"""
219
+
220
+ def __init__(self, hook_event: str, hook_name: str) -> None:
221
+ self.hook_event = hook_event
222
+ self.hook_name = hook_name
223
+ super().__init__()
224
+
225
+
226
+ class HookFinished(Message):
227
+ """Hook 执行完成(携带 stdout/stderr/exit_code)。"""
228
+
229
+ def __init__(
230
+ self,
231
+ hook_event: str,
232
+ hook_name: str,
233
+ outcome: str,
234
+ *,
235
+ stdout: str | None = None,
236
+ stderr: str | None = None,
237
+ exit_codes: list[int] | None = None,
238
+ combined_stdout: str | None = None,
239
+ combined_stderr: str | None = None,
240
+ ) -> None:
241
+ self.hook_event = hook_event
242
+ self.hook_name = hook_name
243
+ self.outcome = outcome
244
+ self.stdout = stdout
245
+ self.stderr = stderr
246
+ self.exit_codes = exit_codes
247
+ self.combined_stdout = combined_stdout
248
+ self.combined_stderr = combined_stderr
249
+ super().__init__()
250
+
251
+
252
+ class TaskStarted(Message):
253
+ """任务启动(对齐 CC task_started)。"""
254
+
255
+ def __init__(
256
+ self,
257
+ task_id: str,
258
+ task_type: str,
259
+ description: str,
260
+ *,
261
+ tool_use_id: str | None = None,
262
+ prompt: str | None = None,
263
+ workflow_name: str | None = None,
264
+ ) -> None:
265
+ self.task_id = task_id
266
+ self.task_type = task_type
267
+ self.description = description
268
+ self.tool_use_id = tool_use_id
269
+ self.prompt = prompt
270
+ self.workflow_name = workflow_name
271
+ super().__init__()
272
+
273
+
274
+ class TaskProgress(Message):
275
+ """任务进度(对齐 CC task_progress)。"""
276
+
277
+ def __init__(
278
+ self,
279
+ task_id: str,
280
+ description: str,
281
+ *,
282
+ usage: dict[str, int] | None = None,
283
+ last_tool_name: str | None = None,
284
+ summary: str | None = None,
285
+ tool_use_id: str | None = None,
286
+ ) -> None:
287
+ self.task_id = task_id
288
+ self.description = description
289
+ self.usage = usage or {}
290
+ self.last_tool_name = last_tool_name
291
+ self.summary = summary
292
+ self.tool_use_id = tool_use_id
293
+ super().__init__()
294
+